Improve dwarfsck

This commit is contained in:
Marcus Holland-Moritz 2020-11-28 23:06:40 +01:00
parent 6da776d4e6
commit 87d547aaae
5 changed files with 95 additions and 42 deletions

View File

@ -46,6 +46,8 @@ class progress;
class filesystem_v2 {
public:
filesystem_v2(logger& lgr, std::shared_ptr<mmif> mm);
filesystem_v2(logger& lgr, std::shared_ptr<mmif> mm,
const block_cache_options& bc_options,
const struct ::stat* stat_defaults = nullptr,

View File

@ -77,6 +77,11 @@ std::shared_ptr<filesystem_v2> s_fs;
void op_init(void* /*userdata*/, struct fuse_conn_info* /*conn*/) {
DEBUG_FUNC("")
log_proxy<debug_logger_policy> log(s_lgr);
auto ti = log.timed_info();
block_cache_options bco;
bco.max_bytes = opts.cachesize;
bco.num_workers = opts.workers;
@ -84,6 +89,8 @@ void op_init(void* /*userdata*/, struct fuse_conn_info* /*conn*/) {
s_fs = std::make_shared<filesystem_v2>(
s_lgr, std::make_shared<mmap>(opts.fsimage), bco, &opts.stat_defaults,
FUSE_ROOT_ID);
ti << "file system initialized";
}
void op_destroy(void* /*userdata*/) {

View File

@ -33,6 +33,7 @@
#include "dwarfs/filesystem_writer.h"
#include "dwarfs/fstypes.h"
#include "dwarfs/inode_reader_v2.h"
#include "dwarfs/options.h"
#include "dwarfs/progress.h"
namespace dwarfs {
@ -330,13 +331,16 @@ ssize_t filesystem_<LoggerPolicy>::readv(uint32_t inode, iovec_read_buf& buf,
} // namespace
filesystem_v2::filesystem_v2(logger& lgr, std::shared_ptr<mmif> mm)
: filesystem_v2(lgr, std::move(mm), block_cache_options()) {}
filesystem_v2::filesystem_v2(logger& lgr, std::shared_ptr<mmif> mm,
const block_cache_options& bc_options,
const struct ::stat* stat_defaults,
int inode_offset)
: impl_(make_unique_logging_object<filesystem_v2::impl, filesystem_,
logger_policies>(
lgr, mm, bc_options, stat_defaults, inode_offset)) {}
lgr, std::move(mm), bc_options, stat_defaults, inode_offset)) {}
void filesystem_v2::rewrite(logger& lgr, progress& prog,
std::shared_ptr<mmif> mm,
@ -412,12 +416,9 @@ void filesystem_v2::identify(logger& lgr, std::shared_ptr<mmif> mm,
}
}
std::vector<uint8_t> schema_raw;
std::vector<uint8_t> meta_raw;
auto meta = make_metadata(lgr, mm, sections, schema_raw, meta_raw);
meta.dump(os, detail_level, [](const std::string&, uint32_t) {});
if (detail_level > 0) {
filesystem_v2(lgr, mm).dump(os, detail_level);
}
}
} // namespace dwarfs

View File

@ -151,8 +151,10 @@ class metadata_ : public metadata_v2::impl {
}
void dump(std::ostream& os, const std::string& indent, entry_view entry,
int detail_level,
std::function<void(const std::string&, uint32_t)> const& icb) const;
void dump(std::ostream& os, const std::string& indent, directory_view dir,
int detail_level,
std::function<void(const std::string&, uint32_t)> const& icb) const;
std::optional<entry_view>
@ -209,6 +211,7 @@ class metadata_ : public metadata_v2::impl {
template <typename LoggerPolicy>
void metadata_<LoggerPolicy>::dump(
std::ostream& os, const std::string& indent, entry_view entry,
int detail_level,
std::function<void(const std::string&, uint32_t)> const& icb) const {
auto mode = entry.mode();
auto inode = entry.inode();
@ -224,9 +227,12 @@ void metadata_<LoggerPolicy>::dump(
uint32_t end = meta_.chunk_index()[inode - chunk_index_offset_ + 1];
os << " [" << beg << ", " << end << "]";
os << " " << file_size(entry, mode) << "\n";
icb(indent + " ", inode);
if (detail_level > 3) {
icb(indent + " ", inode);
}
} else if (S_ISDIR(mode)) {
dump(os, indent + " ", make_directory_view(entry), std::move(icb));
dump(os, indent + " ", make_directory_view(entry), detail_level,
std::move(icb));
} else if (S_ISLNK(mode)) {
os << " -> " << link_value(entry) << "\n";
} else {
@ -237,6 +243,7 @@ void metadata_<LoggerPolicy>::dump(
template <typename LoggerPolicy>
void metadata_<LoggerPolicy>::dump(
std::ostream& os, const std::string& indent, directory_view dir,
int detail_level,
std::function<void(const std::string&, uint32_t)> const& icb) const {
auto count = dir.entry_count();
auto first = dir.first_entry();
@ -245,7 +252,7 @@ void metadata_<LoggerPolicy>::dump(
<< dir.parent_inode() << "]\n";
for (size_t i = 0; i < count; ++i) {
dump(os, indent, make_entry_view(first + i), icb);
dump(os, indent, make_entry_view(first + i), detail_level, icb);
}
}
@ -256,16 +263,22 @@ void metadata_<LoggerPolicy>::dump(
struct ::statvfs stbuf;
statvfs(&stbuf);
os << "block size: " << stbuf.f_bsize << std::endl;
os << "inode count: " << stbuf.f_files << std::endl;
os << "original filesystem size: " << stbuf.f_blocks << std::endl;
if (detail_level > 0) {
analyze_frozen(os, meta_);
os << "block size: " << stbuf.f_bsize << std::endl;
os << "inode count: " << stbuf.f_files << std::endl;
os << "original filesystem size: " << stbuf.f_blocks << std::endl;
}
if (detail_level > 1) {
dump(os, "", root_, icb);
analyze_frozen(os, meta_);
}
if (detail_level > 2) {
dump(os, "", root_, detail_level, icb);
}
if (detail_level > 4) {
os << ::apache::thrift::debugString(meta_.thaw());
}
}

View File

@ -22,39 +22,69 @@
#include <iostream>
#include <vector>
#include <boost/program_options.hpp>
#include <folly/String.h>
#include "dwarfs/filesystem_v2.h"
#include "dwarfs/mmap.h"
#include "dwarfs/options.h"
int main(int argc, char** argv) {
if (argc == 2 || argc == 3) {
try {
dwarfs::stream_logger lgr(std::cerr, dwarfs::logger::DEBUG);
auto mm = std::make_shared<dwarfs::mmap>(argv[1]);
dwarfs::filesystem_v2 fs(lgr, mm, dwarfs::block_cache_options());
namespace dwarfs {
if (argc == 3) {
auto entry = fs.find(argv[2]);
namespace po = boost::program_options;
if (entry) {
struct ::stat stbuf;
fs.getattr(*entry, &stbuf);
std::vector<char> data(stbuf.st_size);
fs.read(stbuf.st_ino, &data[0], data.size(), 0);
std::cout.write(&data[0], data.size());
}
} else {
// TODO: add more usage options...
dwarfs::filesystem_v2::identify(lgr, mm, std::cout, 1);
// fs.dump(std::cout, 1);
}
} catch (const std::exception& e) {
std::cerr << "Error: " << e.what() << std::endl;
return 1;
}
} else {
std::cerr << "Usage: " << argv[0] << " file" << std::endl;
int dwarfsck(int argc, char** argv) {
std::string log_level, input;
int detail;
// clang-format off
po::options_description opts("Command line options");
opts.add_options()
("input,i",
po::value<std::string>(&input),
"input filesystem")
("detail,d",
po::value<int>(&detail)->default_value(1),
"detail level")
("log-level",
po::value<std::string>(&log_level)->default_value("info"),
"log level (error, warn, info, debug, trace)")
("help,h",
"output help message and exit");
// clang-format on
po::positional_options_description pos;
pos.add("input", -1);
po::variables_map vm;
po::store(
po::command_line_parser(argc, argv).options(opts).positional(pos).run(),
vm);
po::notify(vm);
if (vm.count("help") or !vm.count("input")) {
std::cout << "dwarfsck (" << DWARFS_VERSION << ")\n" << opts << std::endl;
return 0;
}
dwarfs::stream_logger lgr(std::cerr, logger::parse_level(log_level));
auto mm = std::make_shared<dwarfs::mmap>(input);
dwarfs::filesystem_v2::identify(lgr, mm, std::cout, detail);
return 0;
}
} // namespace dwarfs
int main(int argc, char** argv) {
try {
return dwarfs::dwarfsck(argc, argv);
} catch (std::exception const& e) {
std::cerr << "ERROR: " << folly::exceptionStr(e) << std::endl;
return 1;
}
}