Commit 11782931 authored by Wayne Kung's avatar Wayne Kung Committed by Commit Bot

cros_healthd: add NVMe wear-level routine

Add NVMe wear-level routine to cros_healthd. The routine examines
weal level against desired threshold.

Bug: b:146513388
Test:
1. chromeos_unittests --gtest_filter
        =CrosHealthdServiceConnectionTest.*
2. unit_tests --gtest_filter
        =DeviceCommandRunRoutineJobTest.*

Change-Id: I3ba7ea651e3c134caa5a7c0253241e7c19ca6601
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2050215
Commit-Queue: Oleh Lamzin <lamzin@google.com>
Reviewed-by: default avatarMaksim Ivanov <emaxx@chromium.org>
Reviewed-by: default avatarOleh Lamzin <lamzin@google.com>
Reviewed-by: default avatarPaul Moy <pmoy@chromium.org>
Reviewed-by: default avatarSteven Bennetts <stevenjb@chromium.org>
Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Cr-Commit-Position: refs/heads/master@{#748624}
parent bcc33180
......@@ -320,6 +320,29 @@ void DeviceCommandRunRoutineJob::RunImpl(CallbackWithResult succeeded_callback,
std::move(failed_callback)));
break;
}
case chromeos::cros_healthd::mojom::DiagnosticRoutineEnum::kNvmeWearLevel: {
constexpr char kWearLevelThresholdFieldName[] = "wearLevelThreshold";
base::Optional<int> wear_level_threshold =
params_dict_.FindIntKey(kWearLevelThresholdFieldName);
// The NVMe wear level routine expects one integer >= 0.
if (!wear_level_threshold.has_value() ||
wear_level_threshold.value() < 0) {
SYSLOG(ERROR) << "Invalid parameters for NVMe wear level routine.";
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(std::move(failed_callback),
std::make_unique<Payload>(
MakeInvalidParametersResponse())));
break;
}
chromeos::cros_healthd::ServiceConnection::GetInstance()
->RunNvmeWearLevelRoutine(
wear_level_threshold.value(),
base::BindOnce(
&DeviceCommandRunRoutineJob::OnCrosHealthdResponseReceived,
weak_ptr_factory_.GetWeakPtr(), std::move(succeeded_callback),
std::move(failed_callback)));
break;
}
}
}
......
......@@ -55,6 +55,10 @@ constexpr char kLengthSecondsFieldName[] = "lengthSeconds";
constexpr char kExpectedStatusFieldName[] = "expectedStatus";
constexpr char kExpectedPowerTypeFieldName[] = "expectedPowerType";
// String constants identifying the parameter fields for the NVMe wear level
// routine.
constexpr char kWearLevelThresholdFieldName[] = "wearLevelThreshold";
// Dummy values to populate cros_healthd's RunRoutineResponse.
constexpr uint32_t kId = 11;
constexpr chromeos::cros_healthd::mojom::DiagnosticRoutineStatusEnum kStatus =
......@@ -991,4 +995,87 @@ TEST_F(DeviceCommandRunRoutineJobTest,
run_loop.Run();
}
TEST_F(DeviceCommandRunRoutineJobTest, RunNvmeWearLevelRoutineSuccess) {
auto run_routine_response =
chromeos::cros_healthd::mojom::RunRoutineResponse::New(kId, kStatus);
chromeos::cros_healthd::FakeCrosHealthdClient::Get()
->SetRunRoutineResponseForTesting(run_routine_response);
base::Value params_dict(base::Value::Type::DICTIONARY);
params_dict.SetIntKey(kWearLevelThresholdFieldName,
/*wear_level_threshold=*/50);
std::unique_ptr<RemoteCommandJob> job =
std::make_unique<DeviceCommandRunRoutineJob>();
InitializeJob(
job.get(), kUniqueID, test_start_time_, base::TimeDelta::FromSeconds(30),
/*terminate_upon_input=*/false,
chromeos::cros_healthd::mojom::DiagnosticRoutineEnum::kNvmeWearLevel,
std::move(params_dict));
base::RunLoop run_loop;
bool success =
job->Run(base::Time::Now(), base::TimeTicks::Now(),
base::BindLambdaForTesting([&]() {
EXPECT_EQ(job->status(), RemoteCommandJob::SUCCEEDED);
std::unique_ptr<std::string> payload = job->GetResultPayload();
EXPECT_TRUE(payload);
EXPECT_EQ(CreateSuccessPayload(kId, kStatus), *payload);
run_loop.Quit();
}));
EXPECT_TRUE(success);
run_loop.Run();
}
TEST_F(DeviceCommandRunRoutineJobTest,
RunNvmeWearLevelRoutineMissingWearLevelThreshold) {
// Test that leaving out the wearLevelThreshold parameter causes the routine
// to fail.
base::Value params_dict(base::Value::Type::DICTIONARY);
std::unique_ptr<RemoteCommandJob> job =
std::make_unique<DeviceCommandRunRoutineJob>();
InitializeJob(
job.get(), kUniqueID, test_start_time_, base::TimeDelta::FromSeconds(30),
/*terminate_upon_input=*/false,
chromeos::cros_healthd::mojom::DiagnosticRoutineEnum::kNvmeWearLevel,
std::move(params_dict));
base::RunLoop run_loop;
bool success =
job->Run(base::Time::Now(), base::TimeTicks::Now(),
base::BindLambdaForTesting([&]() {
EXPECT_EQ(job->status(), RemoteCommandJob::FAILED);
std::unique_ptr<std::string> payload = job->GetResultPayload();
EXPECT_TRUE(payload);
EXPECT_EQ(CreateInvalidParametersFailurePayload(), *payload);
run_loop.Quit();
}));
EXPECT_TRUE(success);
run_loop.Run();
}
TEST_F(DeviceCommandRunRoutineJobTest,
RunNvmeWearLevelRoutineInvalidWearLevelThreshold) {
// Test that a negative wearLevelThreshold parameter causes the routine to
// fail.
base::Value params_dict(base::Value::Type::DICTIONARY);
params_dict.SetIntKey(kWearLevelThresholdFieldName,
/*wear_level_threshold=*/-1);
std::unique_ptr<RemoteCommandJob> job =
std::make_unique<DeviceCommandRunRoutineJob>();
InitializeJob(
job.get(), kUniqueID, test_start_time_, base::TimeDelta::FromSeconds(30),
/*terminate_upon_input=*/false,
chromeos::cros_healthd::mojom::DiagnosticRoutineEnum::kNvmeWearLevel,
std::move(params_dict));
base::RunLoop run_loop;
bool success =
job->Run(base::Time::Now(), base::TimeTicks::Now(),
base::BindLambdaForTesting([&]() {
EXPECT_EQ(job->status(), RemoteCommandJob::FAILED);
std::unique_ptr<std::string> payload = job->GetResultPayload();
EXPECT_TRUE(payload);
EXPECT_EQ(CreateInvalidParametersFailurePayload(), *payload);
run_loop.Quit();
}));
EXPECT_TRUE(success);
run_loop.Run();
}
} // namespace policy
......@@ -88,6 +88,12 @@ void FakeCrosHealthdService::RunFloatingPointAccuracyRoutine(
std::move(callback).Run(run_routine_response_.Clone());
}
void FakeCrosHealthdService::RunNvmeWearLevelRoutine(
uint32_t wear_level_threshold,
RunNvmeWearLevelRoutineCallback callback) {
std::move(callback).Run(run_routine_response_.Clone());
}
void FakeCrosHealthdService::ProbeTelemetryInfo(
const std::vector<mojom::ProbeCategoryEnum>& categories,
ProbeTelemetryInfoCallback callback) {
......
......@@ -61,6 +61,9 @@ class FakeCrosHealthdService final
void RunFloatingPointAccuracyRoutine(
uint32_t length_seconds,
RunFloatingPointAccuracyRoutineCallback callback) override;
void RunNvmeWearLevelRoutine(
uint32_t wear_level_threshold,
RunNvmeWearLevelRoutineCallback callback) override;
// CrosHealthdProbeService overrides:
void ProbeTelemetryInfo(
......
......@@ -70,6 +70,10 @@ class ServiceConnectionImpl : public ServiceConnection {
const base::TimeDelta& exec_duration,
mojom::CrosHealthdDiagnosticsService::
RunFloatingPointAccuracyRoutineCallback callback) override;
void RunNvmeWearLevelRoutine(
uint32_t wear_level_threshold,
mojom::CrosHealthdDiagnosticsService::RunNvmeWearLevelRoutineCallback
callback) override;
void ProbeTelemetryInfo(
const std::vector<mojom::ProbeCategoryEnum>& categories_to_test,
mojom::CrosHealthdProbeService::ProbeTelemetryInfoCallback callback)
......@@ -206,6 +210,16 @@ void ServiceConnectionImpl::RunFloatingPointAccuracyRoutine(
exec_duration.InSeconds(), std::move(callback));
}
void ServiceConnectionImpl::RunNvmeWearLevelRoutine(
uint32_t wear_level_threshold,
mojom::CrosHealthdDiagnosticsService::RunNvmeWearLevelRoutineCallback
callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
BindCrosHealthdDiagnosticsServiceIfNeeded();
cros_healthd_diagnostics_service_->RunNvmeWearLevelRoutine(
wear_level_threshold, std::move(callback));
}
void ServiceConnectionImpl::ProbeTelemetryInfo(
const std::vector<mojom::ProbeCategoryEnum>& categories_to_test,
mojom::CrosHealthdProbeService::ProbeTelemetryInfoCallback callback) {
......
......@@ -105,6 +105,14 @@ class ServiceConnection {
mojom::CrosHealthdDiagnosticsService::
RunFloatingPointAccuracyRoutineCallback callback) = 0;
// Requests that cros_healthd runs the NVMe wear-level routine. See
// src/chromeos/service/cros_healthd/public/mojom/cros_healthd.mojom for
// details.
virtual void RunNvmeWearLevelRoutine(
uint32_t wear_level_threshold,
mojom::CrosHealthdDiagnosticsService::RunNvmeWearLevelRoutineCallback
callback) = 0;
// Gather pieces of information about the platform. See
// src/chromeos/service/cros_healthd/public/mojom/cros_healthd.mojom for
// details.
......
......@@ -39,6 +39,7 @@ std::vector<mojom::DiagnosticRoutineEnum> MakeAvailableRoutines() {
mojom::DiagnosticRoutineEnum::kCpuCache,
mojom::DiagnosticRoutineEnum::kCpuStress,
mojom::DiagnosticRoutineEnum::kFloatingPointAccuracy,
mojom::DiagnosticRoutineEnum::kNvmeWearLevel,
};
}
......@@ -339,6 +340,20 @@ TEST_F(CrosHealthdServiceConnectionTest, RunFloatingPointAccuracyRoutine) {
run_loop.Run();
}
TEST_F(CrosHealthdServiceConnectionTest, RunNvmeWearLevelRoutine) {
// Test that we can run the NVMe wear-level routine.
auto response = MakeRunRoutineResponse();
FakeCrosHealthdClient::Get()->SetRunRoutineResponseForTesting(response);
base::RunLoop run_loop;
ServiceConnection::GetInstance()->RunNvmeWearLevelRoutine(
/*wear_level_threshold=*/50,
base::BindLambdaForTesting([&](mojom::RunRoutineResponsePtr response) {
EXPECT_EQ(response, MakeRunRoutineResponse());
run_loop.Quit();
}));
run_loop.Run();
}
TEST_F(CrosHealthdServiceConnectionTest, ProbeTelemetryInfo) {
// Test that we can send a request without categories.
auto empty_info = mojom::TelemetryInfo::New();
......
......@@ -175,6 +175,21 @@ interface CrosHealthdDiagnosticsService {
// routine.
RunFloatingPointAccuracyRoutine(uint32 length_seconds)
=> (RunRoutineResponse response);
// Requests that the NvmeWearLevel routine is created and started on the
// platform. This routine examines wear level of NVMe against input
// threshold. This routine is only available if GetAvailableRoutines returned
// kNvmeWearLevel.
//
// The request:
// * |wear_level_threshold| - threshold number in percentage which routine
// examines wear level status against.
//
// The response:
// * |response| - contains a unique identifier and status for the created
// routine.
RunNvmeWearLevelRoutine(uint32 wear_level_threshold)
=> (RunRoutineResponse response);
};
// Probe interface exposed by the cros_healthd daemon.
......
......@@ -24,6 +24,7 @@ enum DiagnosticRoutineEnum {
kCpuCache = 5,
kCpuStress = 6,
kFloatingPointAccuracy = 7,
kNvmeWearLevel = 8,
};
// Enumeration of each of the possible statuses for a diagnostics routine.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment