| // Copyright 2022 The ChromiumOS Authors | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #include <base/files/file_path.h> | |
| #include <base/logging.h> | |
| #include <brillo/blkdev_utils/disk_iostat.h> | |
| #include <brillo/flag_helper.h> | |
| #include <brillo/syslog_logging.h> | |
| #include <rootdev/rootdev.h> | |
| #include "discod/controls/file_based_binary_control.h" | |
| #include "discod/controls/real_ufs_write_booster_control_logic.h" | |
| #include "discod/daemon.h" | |
| #include "discod/metrics/real_metrics.h" | |
| #include "discod/utils/ufs.h" | |
| namespace discod { | |
| base::FilePath GetRootDevice() { | |
| char buf[PATH_MAX]; | |
| int ret = | |
| rootdev(buf, PATH_MAX, /*use_slave=*/true, /*strip_partition=*/true); | |
| if (ret == 0) { | |
| return base::FilePath(buf); | |
| } else { | |
| LOG(ERROR) << "Could not query rootdev, error=" << ret; | |
| return base::FilePath(); | |
| } | |
| } | |
| base::FilePath GetRoot() { | |
| return base::FilePath("/"); | |
| } | |
| std::unique_ptr<ControlLoop> MakeControlLoop(const base::FilePath& root_device, | |
| const base::FilePath& root) { | |
| if (!IsUfs(root_device, root)) { | |
| VLOG(1) << "Not a UFS device: " << root_device; | |
| return nullptr; | |
| } | |
| if (!IsWriteBoosterSupported(root_device, root)) { | |
| VLOG(1) << "WriteBooster is not supported: " << root_device; | |
| return nullptr; | |
| } | |
| base::FilePath device_node = GetUfsDeviceNode(root_device, root); | |
| base::FilePath ufs_wb_node = GetUfsWriteBoosterNode(root_device, root); | |
| if (device_node == base::FilePath()) { | |
| LOG(FATAL) << "Could not query iostat node for: " << root_device; | |
| } | |
| if (ufs_wb_node == base::FilePath()) { | |
| LOG(FATAL) << "Could not query ufs wb node for: " << root_device; | |
| } | |
| VLOG(1) << "root_device=" << root_device; | |
| VLOG(1) << "root=" << root; | |
| VLOG(1) << "device_node=" << device_node; | |
| VLOG(1) << "ufs_wb_node=" << ufs_wb_node; | |
| LOG(INFO) << "UFS device found:" << root_device; | |
| std::unique_ptr<RealMetrics> metrics = RealMetrics::Create(); | |
| auto* raw_metrics = metrics.get(); | |
| return std::make_unique<ControlLoop>( | |
| std::make_unique<RealUfsWriteBoosterControlLogic>( | |
| std::make_unique<FileBasedBinaryControl>(ufs_wb_node), raw_metrics), | |
| std::make_unique<brillo::DiskIoStat>(device_node), std::move(metrics)); | |
| } | |
| } // namespace discod | |
| int main(int argc, char** argv) { | |
| DEFINE_bool(foreground, false, "Run in foreground"); | |
| DEFINE_int32(log_level, 0, | |
| "Logging level - 0: LOG(INFO), 1: LOG(WARNING), 2: LOG(ERROR), " | |
| "-1: VLOG(1), -2: VLOG(2), ..."); | |
| DEFINE_string(root_dev, "", "Override root device"); | |
| brillo::FlagHelper::Init(argc, argv, "ChromiumOS Disc Control Daemon"); | |
| brillo::InitLog(brillo::kLogToSyslog | brillo::kLogToStderrIfTty); | |
| logging::SetMinLogLevel(FLAGS_log_level); | |
| if (!FLAGS_foreground) | |
| PCHECK(daemon(0, 0) == 0); | |
| base::FilePath root_device = FLAGS_root_dev.empty() | |
| ? discod::GetRootDevice() | |
| : base::FilePath(FLAGS_root_dev); | |
| LOG(INFO) << "Starting service..."; | |
| const int ret = | |
| discod::Daemon(discod::MakeControlLoop(root_device, discod::GetRoot())) | |
| .Run(); | |
| LOG(INFO) << "Service stopped with exit code " << ret; | |
| } |