feat: add option to generate a debug snapshot of the SysFS (#231)

* feat: daemon implementation for generating sysfs snapshot

* feat: snapshot gui

* fix: dialog title

* chore: update bug reporting info
This commit is contained in:
Ilya Zlobintsev 2023-12-23 10:10:50 +02:00 committed by GitHub
parent 6790c7fa60
commit 9053f1efb5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 491 additions and 45 deletions

307
Cargo.lock generated
View File

@ -49,6 +49,21 @@ dependencies = [
"serde",
]
[[package]]
name = "android-tzdata"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
[[package]]
name = "android_system_properties"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
dependencies = [
"libc",
]
[[package]]
name = "anstream"
version = "0.6.4"
@ -84,7 +99,7 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b"
dependencies = [
"windows-sys",
"windows-sys 0.48.0",
]
[[package]]
@ -94,7 +109,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628"
dependencies = [
"anstyle",
"windows-sys",
"windows-sys 0.48.0",
]
[[package]]
@ -168,11 +183,11 @@ dependencies = [
"futures-lite 2.0.1",
"parking",
"polling 3.3.0",
"rustix 0.38.25",
"rustix 0.38.28",
"slab",
"tracing",
"waker-fn",
"windows-sys",
"windows-sys 0.48.0",
]
[[package]]
@ -208,8 +223,8 @@ dependencies = [
"cfg-if",
"event-listener 3.1.0",
"futures-lite 1.13.0",
"rustix 0.38.25",
"windows-sys",
"rustix 0.38.28",
"windows-sys 0.48.0",
]
[[package]]
@ -235,10 +250,10 @@ dependencies = [
"cfg-if",
"futures-core",
"futures-io",
"rustix 0.38.25",
"rustix 0.38.28",
"signal-hook-registry",
"slab",
"windows-sys",
"windows-sys 0.48.0",
]
[[package]]
@ -331,6 +346,12 @@ dependencies = [
"tracing",
]
[[package]]
name = "bumpalo"
version = "3.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec"
[[package]]
name = "bytemuck"
version = "1.14.0"
@ -413,6 +434,20 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "chrono"
version = "0.4.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38"
dependencies = [
"android-tzdata",
"iana-time-zone",
"js-sys",
"num-traits",
"wasm-bindgen",
"windows-targets 0.48.5",
]
[[package]]
name = "clap"
version = "4.4.8"
@ -642,12 +677,12 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]]
name = "errno"
version = "0.3.7"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f258a7194e7f7c2a7837a8913aeab7fd8c383457034fa20ce4dd3dcb813e8eb8"
checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245"
dependencies = [
"libc",
"windows-sys",
"windows-sys 0.52.0",
]
[[package]]
@ -702,6 +737,18 @@ dependencies = [
"rustc_version",
]
[[package]]
name = "filetime"
version = "0.2.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd"
dependencies = [
"cfg-if",
"libc",
"redox_syscall",
"windows-sys 0.52.0",
]
[[package]]
name = "fnv"
version = "1.0.7"
@ -1142,6 +1189,29 @@ version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
[[package]]
name = "iana-time-zone"
version = "0.1.58"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20"
dependencies = [
"android_system_properties",
"core-foundation-sys",
"iana-time-zone-haiku",
"js-sys",
"wasm-bindgen",
"windows-core",
]
[[package]]
name = "iana-time-zone-haiku"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
dependencies = [
"cc",
]
[[package]]
name = "ident_case"
version = "1.0.1"
@ -1186,7 +1256,7 @@ checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2"
dependencies = [
"hermit-abi",
"libc",
"windows-sys",
"windows-sys 0.48.0",
]
[[package]]
@ -1195,6 +1265,15 @@ version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
[[package]]
name = "js-sys"
version = "0.3.66"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca"
dependencies = [
"wasm-bindgen",
]
[[package]]
name = "lact"
version = "0.5.1"
@ -1233,6 +1312,7 @@ version = "0.5.1"
dependencies = [
"anyhow",
"bincode",
"chrono",
"futures",
"lact-schema",
"libdrm_amdgpu_sys",
@ -1242,6 +1322,7 @@ dependencies = [
"serde_json",
"serde_with",
"serde_yaml",
"tar",
"tokio",
"tracing",
"tracing-subscriber",
@ -1424,7 +1505,7 @@ checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0"
dependencies = [
"libc",
"wasi",
"windows-sys",
"windows-sys 0.48.0",
]
[[package]]
@ -1460,6 +1541,15 @@ dependencies = [
"winapi",
]
[[package]]
name = "num-traits"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c"
dependencies = [
"autocfg",
]
[[package]]
name = "objc"
version = "0.2.7"
@ -1551,7 +1641,7 @@ dependencies = [
"libc",
"redox_syscall",
"smallvec",
"windows-targets",
"windows-targets 0.48.5",
]
[[package]]
@ -1605,7 +1695,7 @@ dependencies = [
"libc",
"log",
"pin-project-lite",
"windows-sys",
"windows-sys 0.48.0",
]
[[package]]
@ -1617,9 +1707,9 @@ dependencies = [
"cfg-if",
"concurrent-queue",
"pin-project-lite",
"rustix 0.38.25",
"rustix 0.38.28",
"tracing",
"windows-sys",
"windows-sys 0.48.0",
]
[[package]]
@ -1808,20 +1898,20 @@ dependencies = [
"io-lifetimes",
"libc",
"linux-raw-sys 0.3.8",
"windows-sys",
"windows-sys 0.48.0",
]
[[package]]
name = "rustix"
version = "0.38.25"
version = "0.38.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc99bc2d4f1fed22595588a013687477aedf3cdcfb26558c559edb67b4d9b22e"
checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316"
dependencies = [
"bitflags 2.4.1",
"errno",
"libc",
"linux-raw-sys 0.4.11",
"windows-sys",
"windows-sys 0.52.0",
]
[[package]]
@ -1989,7 +2079,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9"
dependencies = [
"libc",
"windows-sys",
"windows-sys 0.48.0",
]
[[package]]
@ -2039,6 +2129,17 @@ dependencies = [
"version-compare",
]
[[package]]
name = "tar"
version = "0.4.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b16afcea1f22891c49a00c751c7b63b2233284064f11a200fc624137c51e2ddb"
dependencies = [
"filetime",
"libc",
"xattr",
]
[[package]]
name = "target-lexicon"
version = "0.12.12"
@ -2054,8 +2155,8 @@ dependencies = [
"cfg-if",
"fastrand 2.0.1",
"redox_syscall",
"rustix 0.38.25",
"windows-sys",
"rustix 0.38.28",
"windows-sys 0.48.0",
]
[[package]]
@ -2103,7 +2204,7 @@ dependencies = [
"socket2 0.5.5",
"tokio-macros",
"tracing",
"windows-sys",
"windows-sys 0.48.0",
]
[[package]]
@ -2335,6 +2436,60 @@ version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-bindgen"
version = "0.2.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e"
dependencies = [
"cfg-if",
"wasm-bindgen-macro",
]
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826"
dependencies = [
"bumpalo",
"log",
"once_cell",
"proc-macro2",
"quote",
"syn 2.0.39",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
]
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.39",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f"
[[package]]
name = "winapi"
version = "0.3.9"
@ -2357,13 +2512,31 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-core"
version = "0.51.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64"
dependencies = [
"windows-targets 0.48.5",
]
[[package]]
name = "windows-sys"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
dependencies = [
"windows-targets",
"windows-targets 0.48.5",
]
[[package]]
name = "windows-sys"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
"windows-targets 0.52.0",
]
[[package]]
@ -2372,13 +2545,28 @@ version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
"windows_aarch64_gnullvm 0.48.5",
"windows_aarch64_msvc 0.48.5",
"windows_i686_gnu 0.48.5",
"windows_i686_msvc 0.48.5",
"windows_x86_64_gnu 0.48.5",
"windows_x86_64_gnullvm 0.48.5",
"windows_x86_64_msvc 0.48.5",
]
[[package]]
name = "windows-targets"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd"
dependencies = [
"windows_aarch64_gnullvm 0.52.0",
"windows_aarch64_msvc 0.52.0",
"windows_i686_gnu 0.52.0",
"windows_i686_msvc 0.52.0",
"windows_x86_64_gnu 0.52.0",
"windows_x86_64_gnullvm 0.52.0",
"windows_x86_64_msvc 0.52.0",
]
[[package]]
@ -2387,42 +2575,84 @@ version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea"
[[package]]
name = "windows_aarch64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef"
[[package]]
name = "windows_i686_gnu"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
[[package]]
name = "windows_i686_gnu"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313"
[[package]]
name = "windows_i686_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
[[package]]
name = "windows_i686_msvc"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a"
[[package]]
name = "windows_x86_64_gnu"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e"
[[package]]
name = "windows_x86_64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
[[package]]
name = "winnow"
version = "0.5.19"
@ -2432,6 +2662,17 @@ dependencies = [
"memchr",
]
[[package]]
name = "xattr"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7dae5072fe1f8db8f8d29059189ac175196e410e40ba42d5d4684ae2f750995"
dependencies = [
"libc",
"linux-raw-sys 0.4.11",
"rustix 0.38.28",
]
[[package]]
name = "xdg-home"
version = "1.0.0"

View File

@ -135,9 +135,16 @@ The functionality of the CLI is quite limited. If you want to integrate LACT wit
# Reporting issues
When reporting issues, please include your system info and GPU model.
If you're having an issue with changing the GPU's configuration, it's highly recommended to include a debug snapshot in the bug report.
You can generate one using the option in the dropdown menu:
![image](https://github.com/ilya-zlobintsev/LACT/assets/22796665/36dda5e3-981b-47e7-914e-6e29f30616b4)
The snapshot is an archive which includes the SysFS that LACT uses to interact with the GPU.
If there's a crash, run `lact gui` from the command line to get logs, or use `journalctl -u lactd` to see if the daemon crashed.
If there's a crash, run `lact gui` from the command line to get GUI logs, check daemon logs in `journalctl -u lactd` for errors,
and see `dmesg` for kernel logs that might include information about driver and system issues.
# Alternatives

View File

@ -128,6 +128,7 @@ impl DaemonClient {
request_plain!(get_system_info, SystemInfo, SystemInfo);
request_plain!(enable_overdrive, EnableOverdrive, ());
request_plain!(generate_debug_snapshot, GenerateSnapshot, String);
request_with_id!(get_device_info, DeviceInfo, DeviceInfo);
request_with_id!(get_device_stats, DeviceStats, DeviceStats);
request_with_id!(get_device_clocks_info, DeviceClocksInfo, ClocksInfo);

View File

@ -34,3 +34,5 @@ serde_with = { version = "3.3.0", default-features = false, features = [
] }
zbus = { version = "3.14.1", default-features = false, features = ["tokio"] }
libdrm_amdgpu_sys = { optional = true, version = "0.2.1" }
tar = "0.4.40"
chrono = "0.4.31"

View File

@ -1,21 +1,65 @@
use super::gpu_controller::{fan_control::FanCurve, GpuController};
use super::{
gpu_controller::{fan_control::FanCurve, GpuController},
system::PP_FEATURE_MASK_PATH,
};
use crate::config::{self, default_fan_static_speed, Config, FanControlSettings};
use anyhow::{anyhow, Context};
use lact_schema::{
amdgpu_sysfs::gpu_handle::{
power_profile_mode::PowerProfileModesTable, PerformanceLevel, PowerLevelKind,
amdgpu_sysfs::{
gpu_handle::{
power_profile_mode::PowerProfileModesTable, PerformanceLevel, PowerLevelKind,
},
sysfs::SysFS,
},
default_fan_curve,
request::{ConfirmCommand, SetClocksCommand},
ClocksInfo, DeviceInfo, DeviceListEntry, DeviceStats, FanControlMode, FanCurveMap, PowerStates,
};
use std::{cell::RefCell, collections::BTreeMap, env, path::PathBuf, rc::Rc, time::Duration};
use std::{
cell::RefCell,
collections::BTreeMap,
env,
fs::{File, Permissions},
io::{BufWriter, Cursor, Write},
os::unix::fs::{MetadataExt, PermissionsExt},
path::{Path, PathBuf},
rc::Rc,
time::Duration,
};
use tokio::{sync::oneshot, time::sleep};
use tracing::{debug, error, info, trace, warn};
const CONTROLLERS_LOAD_RETRY_ATTEMPTS: u8 = 5;
const CONTROLLERS_LOAD_RETRY_INTERVAL: u64 = 1;
const SNAPSHOT_GLOBAL_FILES: &[&str] = &[
PP_FEATURE_MASK_PATH,
"/etc/lact/config.yaml",
"/proc/version",
];
const SNAPSHOT_DEVICE_FILES: &[&str] = &[
"uevent",
"vendor",
"pp_cur_state",
"pp_dpm_mclk",
"pp_dpm_pcie",
"pp_dpm_sclk",
"pp_dpm_socclk",
"pp_features",
"pp_force_state",
"pp_mclk_od",
"pp_num_states",
"pp_od_clk_voltage",
"pp_power_profile_mode",
"pp_sclk_od",
"pp_table",
"vbios_version",
"gpu_busy_percent",
"current_link_speed",
"current_link_width",
];
const SNAPSHOT_HWMON_FILE_PREFIXES: &[&str] = &["fan", "pwm", "power", "temp", "freq", "in"];
#[derive(Clone)]
pub struct Handler {
pub config: Rc<RefCell<Config>>,
@ -368,6 +412,62 @@ impl<'a> Handler {
.await
}
pub fn generate_snapshot(&self) -> anyhow::Result<String> {
let datetime = chrono::Local::now().format("%Y%m%d-%H%M%S");
let out_path = format!("/tmp/LACT-sysfs-snapshot-{datetime}.tar");
let out_file = File::create(&out_path)
.with_context(|| "Could not create output file at {out_path}")?;
let out_writer = BufWriter::new(out_file);
let mut archive = tar::Builder::new(out_writer);
for path in SNAPSHOT_GLOBAL_FILES {
let path = Path::new(path);
add_path_to_archive(&mut archive, path)?;
}
for controller in self.gpu_controllers.values() {
let controller_path = controller.handle.get_path();
for device_file in SNAPSHOT_DEVICE_FILES {
let full_path = controller_path.join(device_file);
add_path_to_archive(&mut archive, &full_path)?;
}
for hw_mon in &controller.handle.hw_monitors {
let hw_mon_path = hw_mon.get_path();
let hw_mon_entries =
std::fs::read_dir(hw_mon_path).context("Could not read HwMon dir")?;
'entries: for entry in hw_mon_entries.flatten() {
if !entry.metadata().is_ok_and(|metadata| metadata.is_file()) {
continue;
}
if let Some(name) = entry.file_name().to_str() {
for prefix in SNAPSHOT_HWMON_FILE_PREFIXES {
if name.starts_with(prefix) {
add_path_to_archive(&mut archive, &entry.path())?;
continue 'entries;
}
}
}
}
}
}
let mut writer = archive.into_inner().context("Could not finish archive")?;
writer.flush().context("Could not flush output file")?;
writer
.into_inner()?
.set_permissions(Permissions::from_mode(0o775))
.context("Could not set permissions on output file")?;
Ok(out_path)
}
pub fn confirm_pending_config(&self, command: ConfirmCommand) -> anyhow::Result<()> {
if let Some(tx) = self
.confirm_config_tx
@ -446,3 +546,30 @@ fn load_controllers() -> anyhow::Result<BTreeMap<String, GpuController>> {
Ok(controllers)
}
fn add_path_to_archive(
archive: &mut tar::Builder<impl Write>,
full_path: &Path,
) -> anyhow::Result<()> {
let archive_path = full_path
.strip_prefix("/")
.context("Path should always start at root")?;
if let Ok(metadata) = std::fs::metadata(full_path) {
debug!("adding {full_path:?} to snapshot");
let data = std::fs::read(full_path)
.with_context(|| format!("Could not read file at {full_path:?}"))?;
let mut header = tar::Header::new_gnu();
header.set_size(data.len().try_into().unwrap());
header.set_mode(metadata.mode());
header.set_uid(metadata.uid().into());
header.set_gid(metadata.gid().into());
header.set_cksum();
archive
.append_data(&mut header, archive_path, Cursor::new(data))
.context("Could not write data to archive")?;
}
Ok(())
}

View File

@ -118,6 +118,7 @@ async fn handle_request<'a>(request: Request<'a>, handler: &'a Handler) -> anyho
ok_response(handler.set_enabled_power_states(id, kind, states).await?)
}
Request::EnableOverdrive => ok_response(system::enable_overdrive()?),
Request::GenerateSnapshot => ok_response(handler.generate_snapshot()?),
Request::ConfirmPendingConfig(command) => {
ok_response(handler.confirm_pending_config(command)?)
}

View File

@ -8,7 +8,7 @@ use std::{
};
const PP_OVERDRIVE_MASK: u64 = 0x4000;
const PP_FEATURE_MASK_PATH: &str = "/sys/module/amdgpu/parameters/ppfeaturemask";
pub const PP_FEATURE_MASK_PATH: &str = "/sys/module/amdgpu/parameters/ppfeaturemask";
pub const MODULE_CONF_PATH: &str = "/etc/modprobe.d/99-amdgpu-overdrive.conf";
pub fn info() -> anyhow::Result<SystemInfo<'static>> {

View File

@ -13,16 +13,25 @@ pub struct Header {
impl Header {
pub fn new() -> Self {
let container = HeaderBar::new();
container.set_title_widget(Some(&Box::default())); // Workaround to hide the title
container.set_show_title_buttons(true);
let switcher = StackSwitcher::new();
container.set_title_widget(Some(&switcher));
let gpu_selector = ComboBoxText::new();
container.pack_start(&gpu_selector);
let switcher = StackSwitcher::new();
container.pack_start(&switcher);
let menu = gio::Menu::new();
menu.append(
Some("Generate debug snapshot"),
Some("app.generate-debug-snapshot"),
);
let menu_button = MenuButton::builder()
.icon_name("open-menu-symbolic")
.menu_model(&menu)
.build();
container.pack_end(&menu_button);
Header {
container,

View File

@ -8,6 +8,7 @@ use crate::{APP_ID, GUI_VERSION};
use anyhow::{anyhow, Context};
use apply_revealer::ApplyRevealer;
use glib::clone;
use gtk::gio::ActionEntry;
use gtk::glib::{timeout_future, ControlFlow};
use gtk::{gio::ApplicationFlags, prelude::*, *};
use header::Header;
@ -150,6 +151,14 @@ impl App {
}));
}
let snapshot_action = ActionEntry::builder("generate-debug-snapshot")
.activate(clone!(@strong app => move |_, _, _| {
app.generate_debug_snapshot();
}))
.build();
app.application.add_action_entries([snapshot_action]);
app.start_stats_update_loop(current_gpu_id);
app.window.show();
@ -468,6 +477,54 @@ impl App {
Ok(())
}
fn generate_debug_snapshot(&self) {
match self
.daemon_client
.generate_debug_snapshot()
.and_then(|response| response.inner())
{
Ok(path) => {
let path_label = Label::builder()
.use_markup(true)
.label(format!("<b>{path}</b>"))
.selectable(true)
.build();
let vbox = Box::builder()
.orientation(Orientation::Vertical)
.margin_top(10)
.margin_bottom(10)
.margin_start(10)
.margin_end(10)
.build();
vbox.append(&Label::new(Some("Debug snapshot saved at:")));
vbox.append(&path_label);
let diag = MessageDialog::builder()
.title("Snapshot generated")
.message_type(MessageType::Info)
.use_markup(true)
.text(format!("Debug snapshot saved at <b>{path}</b>"))
.buttons(ButtonsType::Ok)
.transient_for(&self.window)
.build();
let message_box = diag.message_area().downcast::<gtk::Box>().unwrap();
for child in message_box.observe_children().into_iter().flatten() {
if let Ok(label) = child.downcast::<Label>() {
label.set_selectable(true);
}
}
diag.run_async(|diag, _| {
diag.hide();
})
}
Err(err) => show_error(&self.window, err.context("Could not generate snapshot")),
}
}
fn enable_overclocking(&self) {
let text = format!("This will enable the overdrive feature of the amdgpu driver by creating a file at <b>{MODULE_CONF_PATH}</b>. Are you sure you want to do this?");
let dialog = MessageDialog::builder()

View File

@ -56,6 +56,7 @@ pub enum Request<'a> {
states: Vec<u8>,
},
EnableOverdrive,
GenerateSnapshot,
ConfirmPendingConfig(ConfirmCommand),
}