#![feature(file_buffered)] use std::env; use std::fs::File; use std::io::BufRead; use std::io::Write; use std::io::Seek; use std::io::SeekFrom; fn main() { println!("Reading kernel messages..."); let mut kmsg_file = File::open_buffered(env::var("PHENIX_KMSG").unwrap_or(String::from("/dev/kmsg"))) .expect("Failed to open /dev/kmsg"); kmsg_file.seek(SeekFrom::End(0)).expect("Failed to seek to end"); let lines = kmsg_file.lines(); for line in lines { match line { Err(e) => println!("Error reading line: {e}"), Ok(line) => manage_line(line), } } } fn manage_line(line: String) { if let Some((prefix, line)) = line.split_once(";") { if line.ends_with("PCIe link lost") { println!("PCIe link lost {prefix}"); let id = line.splitn(3, " ").nth(1); match id { Some(id) => reset_device(id), None => println!("No device id found in message {line}"), } } } } fn reset_device(id: &str) { println!("Resetting {id}"); echo1(rm_file_path(&id)); echo1(String::from("/sys/bus/pci/rescan")); println!("Rescanned PCI bus"); } fn echo1(path: String) { let rm_file = File::create(&path); match rm_file { Err(e) => println!("Failed to open remove file at {path}: {e}"), Ok(mut file) => { file.write_all(b"1") .expect("Failed to write to remove file"); println!("Removed device {path}"); } } } fn rm_file_path(id: &str) -> String { format!("/sys/bus/pci/devices/{id}/remove") }