externally log result of fsck scans

Summary:
It would be nice to see if there was a fsck on startup, the duration of the fsck, and if it was able to repair all of the problems or not. This diff adds external logging for fsck runs on daemon start.

duration: how long the fsck took
success: false if was not able to repair errors, true if repaired all errors or didn't have to repair at all
attempted_repair: true if we found problems, false otherwise

Reviewed By: chadaustin

Differential Revision: D24774065

fbshipit-source-id: 2fa911652abec889299c74aaa2d53718ed3b4f92
This commit is contained in:
Genevieve Helsel 2020-11-12 13:46:11 -08:00 committed by Facebook GitHub Bot
parent 01b3042a87
commit 4cb299af60
8 changed files with 90 additions and 21 deletions

View File

@ -203,7 +203,8 @@ EdenMount::EdenMount(
blobAccess_{objectStore_, blobCache_},
overlay_{Overlay::create(
config_->getOverlayPath(),
config_->getCaseSensitive())},
config_->getCaseSensitive(),
serverState_->getStructuredLogger())},
#ifndef _WIN32
overlayFileAccess_{overlay_.get()},
#endif

View File

@ -17,6 +17,7 @@
#include <folly/io/Cursor.h>
#include <folly/io/IOBuf.h>
#include <folly/logging/xlog.h>
#include <folly/stop_watch.h>
#include <thrift/lib/cpp2/protocol/Serializer.h>
#include "eden/fs/inodes/DirEntry.h"
#include "eden/fs/inodes/InodeBase.h"
@ -42,16 +43,25 @@ using std::optional;
std::shared_ptr<Overlay> Overlay::create(
AbsolutePathPiece localDir,
bool caseSensitive) {
bool caseSensitive,
std::shared_ptr<StructuredLogger> logger) {
struct MakeSharedEnabler : public Overlay {
explicit MakeSharedEnabler(AbsolutePathPiece localDir, bool caseSensitive)
: Overlay(localDir, caseSensitive) {}
explicit MakeSharedEnabler(
AbsolutePathPiece localDir,
bool caseSensitive,
std::shared_ptr<StructuredLogger> logger)
: Overlay(localDir, caseSensitive, logger) {}
};
return std::make_shared<MakeSharedEnabler>(localDir, caseSensitive);
return std::make_shared<MakeSharedEnabler>(localDir, caseSensitive, logger);
}
Overlay::Overlay(AbsolutePathPiece localDir, bool caseSensitive)
: backingOverlay_{localDir}, caseSensitive_{caseSensitive} {}
Overlay::Overlay(
AbsolutePathPiece localDir,
bool caseSensitive,
std::shared_ptr<StructuredLogger> logger)
: backingOverlay_{localDir},
caseSensitive_{caseSensitive},
structuredLogger_{logger} {}
Overlay::~Overlay() {
close();
@ -151,8 +161,21 @@ void Overlay::initOverlay(
<< " was not shut down cleanly. Performing fsck scan.";
OverlayChecker checker(&backingOverlay_, std::nullopt);
folly::stop_watch<> fsckRuntime;
checker.scanForErrors(progressCallback);
checker.repairErrors();
auto result = checker.repairErrors();
auto fsckRuntimeInSeconds =
std::chrono::duration<double>{fsckRuntime.elapsed()}.count();
if (result) {
// If totalErrors - fixedErrors is nonzero, then we failed to
// fix all of the problems.
auto success = !(result->totalErrors - result->fixedErrors);
structuredLogger_->logEvent(
Fsck{fsckRuntimeInSeconds, success, true /*attempted_repair*/});
} else {
structuredLogger_->logEvent(Fsck{
fsckRuntimeInSeconds, true /*success*/, false /*attempted_repair*/});
}
optNextInodeNumber = checker.getNextInodeNumber();
#else

View File

@ -20,6 +20,7 @@
#include "eden/fs/inodes/overlay/OverlayChecker.h"
#include "eden/fs/inodes/overlay/gen-cpp2/overlay_types.h"
#include "eden/fs/inodes/sqliteoverlay/SqliteOverlay.h"
#include "eden/fs/telemetry/StructuredLogger.h"
#include "eden/fs/utils/DirType.h"
#include "eden/fs/utils/PathFuncs.h"
@ -74,7 +75,8 @@ class Overlay : public std::enable_shared_from_this<Overlay> {
*/
static std::shared_ptr<Overlay> create(
AbsolutePathPiece localDir,
bool caseSensitive);
bool caseSensitive,
std::shared_ptr<StructuredLogger> logger);
~Overlay();
@ -217,7 +219,10 @@ class Overlay : public std::enable_shared_from_this<Overlay> {
struct statfs statFs();
#endif // !_WIN32
private:
explicit Overlay(AbsolutePathPiece localDir, bool caseSensitive);
explicit Overlay(
AbsolutePathPiece localDir,
bool caseSensitive,
std::shared_ptr<StructuredLogger> logger);
/**
* A request for the background GC thread. There are two types of requests:
@ -300,6 +305,8 @@ class Overlay : public std::enable_shared_from_this<Overlay> {
folly::Baton<> lastOutstandingRequestIsComplete_;
bool caseSensitive_;
std::shared_ptr<StructuredLogger> structuredLogger_;
friend class IORequest;
};

View File

@ -719,7 +719,7 @@ optional<OverlayChecker::RepairResult> OverlayChecker::repairErrors() {
}
}
auto numUnfixed = errors_.size() - result.fixedErrors;
auto numUnfixed = result.totalErrors - result.fixedErrors;
string finalMsg;
if (numUnfixed) {
finalMsg = folly::to<string>(

View File

@ -11,6 +11,7 @@
#include <stdlib.h>
#include "eden/fs/inodes/DirEntry.h"
#include "eden/fs/inodes/Overlay.h"
#include "eden/fs/telemetry/NullStructuredLogger.h"
using namespace facebook::eden;
using namespace folly::string_piece_literals;
@ -26,7 +27,10 @@ void benchmarkOverlayTreeWrites(AbsolutePathPiece overlayPath) {
//
// overlayPath is parameterized to measure on different filesystem types.
auto overlay = Overlay::create(overlayPath, kPathMapDefaultCaseSensitive);
auto overlay = Overlay::create(
overlayPath,
kPathMapDefaultCaseSensitive,
std::make_shared<NullStructuredLogger>());
overlay->initialize().get();
Hash hash1{folly::ByteRange{"abcdabcdabcdabcdabcd"_sp}};

View File

@ -29,6 +29,7 @@
#include "eden/fs/inodes/OverlayFile.h"
#include "eden/fs/inodes/TreeInode.h"
#include "eden/fs/service/PrettyPrinters.h"
#include "eden/fs/telemetry/NullStructuredLogger.h"
#include "eden/fs/testharness/FakeBackingStore.h"
#include "eden/fs/testharness/FakeTreeBuilder.h"
#include "eden/fs/testharness/TempFile.h"
@ -65,7 +66,8 @@ TEST(OverlayGoldMasterTest, can_load_overlay_v2) {
auto overlay = Overlay::create(
realpath(tmpdir.path().string()) + "overlay-v2"_pc,
kPathMapDefaultCaseSensitive);
kPathMapDefaultCaseSensitive,
std::make_shared<NullStructuredLogger>());
overlay->initialize().get();
Hash hash1{folly::ByteRange{"abcdabcdabcdabcdabcd"_sp}};
@ -259,7 +261,9 @@ TEST_F(OverlayTest, getFilePath) {
TEST(PlainOverlayTest, new_overlay_is_clean) {
folly::test::TemporaryDirectory testDir;
auto overlay = Overlay::create(
AbsolutePath{testDir.path().string()}, kPathMapDefaultCaseSensitive);
AbsolutePath{testDir.path().string()},
kPathMapDefaultCaseSensitive,
std::make_shared<NullStructuredLogger>());
overlay->initialize().get();
EXPECT_TRUE(overlay->hadCleanStartup());
}
@ -268,12 +272,16 @@ TEST(PlainOverlayTest, reopened_overlay_is_clean) {
folly::test::TemporaryDirectory testDir;
{
auto overlay = Overlay::create(
AbsolutePath{testDir.path().string()}, kPathMapDefaultCaseSensitive);
AbsolutePath{testDir.path().string()},
kPathMapDefaultCaseSensitive,
std::make_shared<NullStructuredLogger>());
overlay->initialize().get();
}
auto overlay = Overlay::create(
AbsolutePath{testDir.path().string()}, kPathMapDefaultCaseSensitive);
AbsolutePath{testDir.path().string()},
kPathMapDefaultCaseSensitive,
std::make_shared<NullStructuredLogger>());
overlay->initialize().get();
EXPECT_TRUE(overlay->hadCleanStartup());
}
@ -284,7 +292,9 @@ TEST(PlainOverlayTest, unclean_overlay_is_dirty) {
{
auto overlay = Overlay::create(
AbsolutePath{testDir.path().string()}, kPathMapDefaultCaseSensitive);
AbsolutePath{testDir.path().string()},
kPathMapDefaultCaseSensitive,
std::make_shared<NullStructuredLogger>());
overlay->initialize().get();
}
@ -293,7 +303,9 @@ TEST(PlainOverlayTest, unclean_overlay_is_dirty) {
}
auto overlay = Overlay::create(
AbsolutePath{testDir.path().string()}, kPathMapDefaultCaseSensitive);
AbsolutePath{testDir.path().string()},
kPathMapDefaultCaseSensitive,
std::make_shared<NullStructuredLogger>());
overlay->initialize().get();
EXPECT_FALSE(overlay->hadCleanStartup());
}
@ -330,7 +342,10 @@ class RawOverlayTest : public ::testing::TestWithParam<OverlayRestartMode> {
}
void loadOverlay() {
overlay = Overlay::create(getLocalDir(), kPathMapDefaultCaseSensitive);
overlay = Overlay::create(
getLocalDir(),
kPathMapDefaultCaseSensitive,
std::make_shared<NullStructuredLogger>());
overlay->initialize().get();
}
@ -732,7 +747,8 @@ class DebugDumpOverlayInodesTest : public ::testing::Test {
: testDir_{makeTempDir("eden_DebugDumpOverlayInodesTest")},
overlay{Overlay::create(
AbsolutePathPiece{testDir_.path().string()},
kPathMapDefaultCaseSensitive)} {
kPathMapDefaultCaseSensitive,
std::make_shared<NullStructuredLogger>())} {
overlay->initialize().get();
}

View File

@ -11,6 +11,7 @@
#include "eden/fs/inodes/DirEntry.h"
#include "eden/fs/inodes/Overlay.h"
#include "eden/fs/inodes/OverlayFile.h"
#include "eden/fs/telemetry/NullStructuredLogger.h"
using namespace facebook::eden;
using namespace folly::string_piece_literals;
@ -37,7 +38,10 @@ void createGoldMasterOverlay(AbsolutePath overlayPath) {
Hash hash3{folly::ByteRange{"e0e0e0e0e0e0e0e0e0e0"_sp}};
Hash hash4{folly::ByteRange{"44444444444444444444"_sp}};
auto overlay = Overlay::create(overlayPath, kPathMapCaseSensitive);
auto overlay = Overlay::create(
overlayPath,
kPathMapCaseSensitive,
std::make_shared<NullStructuredLogger>());
auto fileInode = overlay->allocateInodeNumber();
XCHECK_EQ(2_ino, fileInode);

View File

@ -58,6 +58,20 @@ class DynamicEvent {
DoubleMap doubles_;
};
struct Fsck {
static constexpr const char* type = "fsck";
double duration = 0.0;
bool success = false;
bool attempted_repair = false;
void populate(DynamicEvent& event) const {
event.addDouble("duration", duration);
event.addBool("success", success);
event.addBool("attempted_repair", attempted_repair);
}
};
struct FetchHeavy {
static constexpr const char* type = "fetch_heavy";