From 87d547aaae676b30a65340fc0098339d03ddf230 Mon Sep 17 00:00:00 2001 From: Marcus Holland-Moritz Date: Sat, 28 Nov 2020 23:06:40 +0100 Subject: [PATCH] Improve dwarfsck --- include/dwarfs/filesystem_v2.h | 2 + src/dwarfs.cpp | 7 +++ src/dwarfs/filesystem_v2.cpp | 15 ++++--- src/dwarfs/metadata_v2.cpp | 31 +++++++++---- src/dwarfsck.cpp | 82 +++++++++++++++++++++++----------- 5 files changed, 95 insertions(+), 42 deletions(-) diff --git a/include/dwarfs/filesystem_v2.h b/include/dwarfs/filesystem_v2.h index 88c0138a..2342d067 100644 --- a/include/dwarfs/filesystem_v2.h +++ b/include/dwarfs/filesystem_v2.h @@ -46,6 +46,8 @@ class progress; class filesystem_v2 { public: + filesystem_v2(logger& lgr, std::shared_ptr mm); + filesystem_v2(logger& lgr, std::shared_ptr mm, const block_cache_options& bc_options, const struct ::stat* stat_defaults = nullptr, diff --git a/src/dwarfs.cpp b/src/dwarfs.cpp index b51daf52..ed4c46a4 100644 --- a/src/dwarfs.cpp +++ b/src/dwarfs.cpp @@ -77,6 +77,11 @@ std::shared_ptr s_fs; void op_init(void* /*userdata*/, struct fuse_conn_info* /*conn*/) { DEBUG_FUNC("") + + log_proxy 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( s_lgr, std::make_shared(opts.fsimage), bco, &opts.stat_defaults, FUSE_ROOT_ID); + + ti << "file system initialized"; } void op_destroy(void* /*userdata*/) { diff --git a/src/dwarfs/filesystem_v2.cpp b/src/dwarfs/filesystem_v2.cpp index b424c645..2c1024ff 100644 --- a/src/dwarfs/filesystem_v2.cpp +++ b/src/dwarfs/filesystem_v2.cpp @@ -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_::readv(uint32_t inode, iovec_read_buf& buf, } // namespace +filesystem_v2::filesystem_v2(logger& lgr, std::shared_ptr mm) + : filesystem_v2(lgr, std::move(mm), block_cache_options()) {} + filesystem_v2::filesystem_v2(logger& lgr, std::shared_ptr mm, const block_cache_options& bc_options, const struct ::stat* stat_defaults, int inode_offset) : impl_(make_unique_logging_object( - 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 mm, @@ -412,12 +416,9 @@ void filesystem_v2::identify(logger& lgr, std::shared_ptr mm, } } - std::vector schema_raw; - std::vector 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 diff --git a/src/dwarfs/metadata_v2.cpp b/src/dwarfs/metadata_v2.cpp index c042b7cb..e11d6562 100644 --- a/src/dwarfs/metadata_v2.cpp +++ b/src/dwarfs/metadata_v2.cpp @@ -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 const& icb) const; void dump(std::ostream& os, const std::string& indent, directory_view dir, + int detail_level, std::function const& icb) const; std::optional @@ -209,6 +211,7 @@ class metadata_ : public metadata_v2::impl { template void metadata_::dump( std::ostream& os, const std::string& indent, entry_view entry, + int detail_level, std::function const& icb) const { auto mode = entry.mode(); auto inode = entry.inode(); @@ -224,9 +227,12 @@ void metadata_::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_::dump( template void metadata_::dump( std::ostream& os, const std::string& indent, directory_view dir, + int detail_level, std::function const& icb) const { auto count = dir.entry_count(); auto first = dir.first_entry(); @@ -245,7 +252,7 @@ void metadata_::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_::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()); } } diff --git a/src/dwarfsck.cpp b/src/dwarfsck.cpp index bd6008c1..58cfd784 100644 --- a/src/dwarfsck.cpp +++ b/src/dwarfsck.cpp @@ -22,39 +22,69 @@ #include #include +#include + +#include + #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(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 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(&input), + "input filesystem") + ("detail,d", + po::value(&detail)->default_value(1), + "detail level") + ("log-level", + po::value(&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(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; + } +}