mirror of
https://github.com/miskcoo/ugreen_dx4600_leds_controller.git
synced 2025-07-23 12:23:09 +02:00
Add an optional compiled disk activities monitor to reduce the CPU usage (#38)
Some checks are pending
Build kernel module for TrueNAS / build-and-run (push) Waiting to run
Some checks are pending
Build kernel module for TrueNAS / build-and-run (push) Waiting to run
This commit is contained in:
@@ -211,6 +211,15 @@ Please see `scripts/ugreen-leds.conf` for an example.
|
|||||||
systemctl enable ugreen-diskiomon
|
systemctl enable ugreen-diskiomon
|
||||||
```
|
```
|
||||||
|
|
||||||
|
- (_Optional_) To reduce the CPU usage of blinking LEDs when disks are active, you can enter the `scripts` directory and do the following things:
|
||||||
|
```bash
|
||||||
|
# compile the disk activities monitor
|
||||||
|
g++ -std=c++17 -O2 blink-disk.cpp -o ugreen-blink-disk
|
||||||
|
|
||||||
|
# copy the binary file (the path can be changed, see BLINK_MON_PATH in ugreen-leds.conf)
|
||||||
|
cp ugreen-blink-disk /usr/bin
|
||||||
|
```
|
||||||
|
|
||||||
## Disk Mapping
|
## Disk Mapping
|
||||||
|
|
||||||
To make the disk LEDs useful, we should map the disk LEDs to correct disk slots. First of all, we should highlight that using `/dev/sdX` is never a smart idea, as it may change at every boot.
|
To make the disk LEDs useful, we should map the disk LEDs to correct disk slots. First of all, we should highlight that using `/dev/sdX` is never a smart idea, as it may change at every boot.
|
||||||
|
73
scripts/blink-disk.cpp
Normal file
73
scripts/blink-disk.cpp
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
#include <fstream>
|
||||||
|
#include <thread>
|
||||||
|
#include <vector>
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
if (argc < 4 || argc % 2 != 0) {
|
||||||
|
std::cerr << "Usage: " << argv[0] << " <sleep time (in second)>"
|
||||||
|
<< " <block device 1> <led device 1> <block device 2> <led device 2>...\n";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int num_devices = (argc - 2) / 2;
|
||||||
|
int sleep_time_ms = int(std::stod(argv[1]) * 1000);
|
||||||
|
|
||||||
|
std::vector<std::string> block_device_stat_paths;
|
||||||
|
std::vector<std::string> led_device_shot_paths;
|
||||||
|
|
||||||
|
for (int i = 0; i < num_devices; i++) {
|
||||||
|
std::string block_device = argv[2 + 2 * i];
|
||||||
|
std::string led_device = argv[3 + 2 * i];
|
||||||
|
|
||||||
|
block_device_stat_paths.push_back(
|
||||||
|
"/sys/block/" + block_device + "/stat");
|
||||||
|
led_device_shot_paths.push_back(
|
||||||
|
"/sys/class/leds/" + led_device + "/shot");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<bool> device_status(num_devices, true);
|
||||||
|
std::vector<std::string> old_lines(num_devices);
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
for (int i = 0; i < num_devices; i++) {
|
||||||
|
|
||||||
|
if (!device_status[i]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ifstream stat_file(block_device_stat_paths[i]);
|
||||||
|
|
||||||
|
if (!stat_file.is_open()) {
|
||||||
|
std::cerr << "Failed to open " << block_device_stat_paths[i] << "\n";
|
||||||
|
device_status[i] = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string line;
|
||||||
|
std::getline(stat_file, line);
|
||||||
|
stat_file.close();
|
||||||
|
|
||||||
|
if (line != old_lines[i]) {
|
||||||
|
|
||||||
|
std::ofstream led_file(led_device_shot_paths[i]);
|
||||||
|
if (!led_file.is_open()) {
|
||||||
|
std::cerr << "Failed to open " << led_device_shot_paths[i] << "\n";
|
||||||
|
device_status[i] = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
led_file << "1";
|
||||||
|
led_file.close();
|
||||||
|
|
||||||
|
old_lines[i] = std::move(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(sleep_time_ms));
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@@ -228,7 +228,7 @@ if [ "$CHECK_ZPOOL" = true ]; then
|
|||||||
|
|
||||||
if [[ "${zpool_dev_state}" != "ONLINE" ]]; then
|
if [[ "${zpool_dev_state}" != "ONLINE" ]]; then
|
||||||
echo "$COLOR_ZPOOL_FAIL" > /sys/class/leds/$led/color
|
echo "$COLOR_ZPOOL_FAIL" > /sys/class/leds/$led/color
|
||||||
echo Disk failure detected on /dev/$dev at $(date +%Y-%m-%d' '%H:%M:%S)
|
echo Disk failure detected on /dev/$zpool_dev_name at $(date +%Y-%m-%d' '%H:%M:%S)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# ==== To recover from an error, you should restart the script ====
|
# ==== To recover from an error, you should restart the script ====
|
||||||
@@ -316,20 +316,34 @@ fi
|
|||||||
disk_online_check_pid=$!
|
disk_online_check_pid=$!
|
||||||
|
|
||||||
# monitor disk activities
|
# monitor disk activities
|
||||||
declare -A diskio_data_rw
|
BLINK_MON_PATH=${BLINK_MON_PATH:=/usr/bin/ugreen-blink-disk}
|
||||||
while true; do
|
if [ -f "${BLINK_MON_PATH}" ]; then
|
||||||
for led in "${!devices[@]}"; do
|
|
||||||
|
|
||||||
# if $dev does not exist, diskio_new_rw="", which will be safe
|
diskiomon_parameters() {
|
||||||
diskio_new_rw="$(cat /sys/block/${devices[$led]}/stat 2>/dev/null)"
|
echo ${LED_REFRESH_INTERVAL}
|
||||||
|
for led in "${!devices[@]}"; do
|
||||||
|
echo ${devices[$led]} $led
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
if [ "${diskio_data_rw[$led]}" != "${diskio_new_rw}" ]; then
|
${BLINK_MON_PATH} $(diskiomon_parameters)
|
||||||
echo 1 > /sys/class/leds/$led/shot
|
|
||||||
fi
|
else
|
||||||
|
declare -A diskio_data_rw
|
||||||
|
while true; do
|
||||||
|
for led in "${!devices[@]}"; do
|
||||||
|
|
||||||
|
# if $dev does not exist, diskio_new_rw="", which will be safe
|
||||||
|
diskio_new_rw="$(cat /sys/block/${devices[$led]}/stat 2>/dev/null)"
|
||||||
|
|
||||||
|
if [ "${diskio_data_rw[$led]}" != "${diskio_new_rw}" ]; then
|
||||||
|
echo 1 > /sys/class/leds/$led/shot
|
||||||
|
fi
|
||||||
|
|
||||||
|
diskio_data_rw[$led]=$diskio_new_rw
|
||||||
|
done
|
||||||
|
|
||||||
|
sleep ${LED_REFRESH_INTERVAL}s
|
||||||
|
|
||||||
diskio_data_rw[$led]=$diskio_new_rw
|
|
||||||
done
|
done
|
||||||
|
fi
|
||||||
sleep ${LED_REFRESH_INTERVAL}s
|
|
||||||
|
|
||||||
done
|
|
||||||
|
@@ -20,6 +20,9 @@
|
|||||||
# and fill the DISK_SERIAL array below (see the comments therein).
|
# and fill the DISK_SERIAL array below (see the comments therein).
|
||||||
MAPPING_METHOD=ata
|
MAPPING_METHOD=ata
|
||||||
|
|
||||||
|
# The path of the compiled diskio monitor (OPTIONAL)
|
||||||
|
BLINK_MON_PATH=/usr/bin/ugreen-blink-disk
|
||||||
|
|
||||||
# The serial numbers of disks (used only when MAPPING_METHOD=serial)
|
# The serial numbers of disks (used only when MAPPING_METHOD=serial)
|
||||||
# You need to record them before inserting to your NAS, and the corresponding disk slots.
|
# You need to record them before inserting to your NAS, and the corresponding disk slots.
|
||||||
# If you have 4 disks, with serial numbers: SN1 SN2 SN3 SN4,
|
# If you have 4 disks, with serial numbers: SN1 SN2 SN3 SN4,
|
||||||
|
Reference in New Issue
Block a user