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"
21 class RecoveryDriver {
23 // If true, overwrite structures that generate decoding errors.
26 // If true, overwrite root objects during init_roots even if they
32 librados::Rados &rados,
33 std::string &metadata_pool_name,
35 fs_cluster_id_t fscid) = 0;
37 void set_force_corrupt(const bool val)
42 void set_force_init(const bool val)
49 * Inject an inode + dentry parents into the metadata pool,
50 * based on a backtrace recovered from the data pool
52 virtual int inject_with_backtrace(
53 const inode_backtrace_t &bt,
54 const InodeStore &dentry) = 0;
57 * Inject an inode + dentry into the lost+found directory,
58 * when all we know about a file is its inode.
60 virtual int inject_lost_and_found(
62 const InodeStore &dentry) = 0;
65 * Create any missing roots (i.e. mydir, strays, root inode)
67 virtual int init_roots(
68 int64_t data_pool_id) = 0;
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.
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
81 virtual int check_roots(bool *result) = 0;
84 * Helper to compose dnames for links to lost+found
87 std::string lost_found_dname(inodeno_t ino)
90 snprintf(s, sizeof(s), "%llx", (unsigned long long)ino);
91 return std::string(s);
95 : force_corrupt(false),
99 virtual ~RecoveryDriver() {}
102 class LocalFileDriver : public RecoveryDriver
105 const std::string path;
106 librados::IoCtx &data_io;
109 const std::string &file_path,
115 LocalFileDriver(const std::string &path_, librados::IoCtx &data_io_)
116 : RecoveryDriver(), path(path_), data_io(data_io_)
119 // Implement RecoveryDriver interface
121 librados::Rados &rados,
122 std::string &metadata_pool_name,
124 fs_cluster_id_t fscid) override;
126 int inject_with_backtrace(
127 const inode_backtrace_t &bt,
128 const InodeStore &dentry) override;
130 int inject_lost_and_found(
132 const InodeStore &dentry) override;
134 int init_roots(int64_t data_pool_id) override;
136 int check_roots(bool *result) override;
140 * A class that knows how to work with objects in a CephFS
147 librados::IoCtx metadata_io;
150 * Construct a synthetic InodeStore for a normal file
152 void build_file_dentry(
153 inodeno_t ino, uint64_t file_size, time_t file_mtime,
154 const file_layout_t &layout,
158 * Construct a synthetic InodeStore for a directory
160 void build_dir_dentry(
162 const frag_info_t &fragstat,
163 const file_layout_t &layout,
167 * Try and read an fnode from a dirfrag
169 int read_fnode(inodeno_t ino, frag_t frag,
170 fnode_t *fnode, uint64_t *read_version);
173 * Try and read a dentry from a dirfrag
175 int read_dentry(inodeno_t parent_ino, frag_t frag,
176 const std::string &dname, InodeStore *inode);
180 * A class that knows how to manipulate CephFS metadata pools
182 class MetadataDriver : public RecoveryDriver, public MetadataTool
186 * Create a .inode object, i.e. root or mydir
188 int inject_unlinked_inode(inodeno_t inono, int mode, int64_t data_pool_id);
191 * Check for existence of .inode objects, before
192 * trying to go ahead and inject metadata.
194 int root_exists(inodeno_t ino, bool *result);
195 int find_or_create_dirfrag(
202 * Work out which fragment of a directory should contain a named
203 * dentry, recursing up the trace as necessary to retrieve
208 const std::string &dname,
213 // Implement RecoveryDriver interface
215 librados::Rados &rados,
216 std::string &metadata_pool_name,
218 fs_cluster_id_t fscid) override;
221 inodeno_t dir_ino, const std::string &dname,
222 const frag_t fragment, const InodeStore &inode);
224 int inject_with_backtrace(
225 const inode_backtrace_t &bt,
226 const InodeStore &dentry) override;
228 int inject_lost_and_found(
230 const InodeStore &dentry) override;
232 int init_roots(int64_t data_pool_id) override;
234 int check_roots(bool *result) override;
237 class DataScan : public MDSUtility, public MetadataTool
240 RecoveryDriver *driver;
241 fs_cluster_id_t fscid;
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;
253 * Scan data pool for backtraces, and inject inodes to metadata pool
258 * Scan data pool for file sizes and mtimes
263 * Scan metadata pool for 0th dirfrags to link orphaned
269 * Cleanup xattrs from data pool
274 * Check if an inode number is in the permitted ranges
276 bool valid_ino(inodeno_t ino) const;
281 // Accept pools which are not in the FSMap
283 // Respond to decode errors by overwriting
285 // Overwrite root objects even if they exist
287 // Only scan inodes without this scrub tag
291 * @param r set to error on valid key with invalid value
292 * @return true if argument consumed, else false
295 const std::vector<const char*> &args,
296 std::vector<const char *>::const_iterator &i,
300 * @return true if argument consumed, else false
303 const std::vector<const char*> &arg,
304 std::vector<const char *>::const_iterator &i);
306 int probe_filter(librados::IoCtx &ioctx);
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.
314 librados::IoCtx &ioctx,
316 std::function<int(std::string, uint64_t, uint64_t)> handler);
320 int main(const std::vector<const char *> &args);
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),