xref: /DragonOS/kernel/src/filesystem/procfs/kmsg.rs (revision f79998f626801329580c782fd05e36cb2027f474)
1 use core::sync::atomic::{compiler_fence, Ordering};
2 
3 use super::log::{LogLevel, LogMessage};
4 
5 use crate::libs::spinlock::SpinLock;
6 
7 use alloc::{borrow::ToOwned, string::ToString, vec::Vec};
8 
9 use kdepends::ringbuffer::{AllocRingBuffer, RingBuffer};
10 
11 use log::info;
12 use system_error::SystemError;
13 
14 /// 缓冲区容量
15 const KMSG_BUFFER_CAPACITY: usize = 1024;
16 
17 /// 全局环形缓冲区
18 pub static mut KMSG: Option<SpinLock<Kmsg>> = None;
19 
20 /// 初始化KMSG
21 pub fn kmsg_init() {
22     info!("kmsg_init");
23     let kmsg = SpinLock::new(Kmsg::new());
24 
25     compiler_fence(Ordering::SeqCst);
26     unsafe { KMSG = Some(kmsg) };
27     compiler_fence(Ordering::SeqCst);
28     info!("kmsg_init done");
29 }
30 
31 /// 日志
32 pub struct Kmsg {
33     /// 环形缓冲区
34     buffer: AllocRingBuffer<LogMessage>,
35     /// 缓冲区字节数组
36     data: Vec<u8>,
37     /// 能够输出到控制台的日志级别,当console_loglevel为DEFAULT时,表示可以打印所有级别的日志消息到控制台
38     console_loglevel: LogLevel,
39     /// 判断buffer在上一次转成字节数组之后是否发生变动
40     is_changed: bool,
41 }
42 
43 impl Kmsg {
44     pub fn new() -> Self {
45         Kmsg {
46             buffer: AllocRingBuffer::new(KMSG_BUFFER_CAPACITY),
47             data: Vec::new(),
48             console_loglevel: LogLevel::DEFAULT,
49             is_changed: false,
50         }
51     }
52 
53     /// 添加日志消息
54     pub fn push(&mut self, msg: LogMessage) {
55         self.buffer.push(msg);
56         self.is_changed = true;
57     }
58 
59     /// 读取缓冲区
60     pub fn read(&mut self, buf: &mut [u8]) -> Result<usize, SystemError> {
61         self.tobytes();
62 
63         match self.console_loglevel {
64             LogLevel::DEFAULT => self.read_all(buf),
65             _ => self.read_level(buf),
66         }
67     }
68 
69     /// 读取缓冲区所有日志消息
70     fn read_all(&mut self, buf: &mut [u8]) -> Result<usize, SystemError> {
71         let len = self.data.len().min(buf.len());
72 
73         // 拷贝数据
74         let src = &self.data[0..len];
75         buf[0..len].copy_from_slice(src);
76 
77         return Ok(len);
78     }
79 
80     /// 读取缓冲区特定level的日志消息
81     fn read_level(&mut self, buf: &mut [u8]) -> Result<usize, SystemError> {
82         let mut data_level: Vec<u8> = Vec::new();
83 
84         for msg in self.buffer.iter() {
85             if msg.level() == self.console_loglevel {
86                 data_level.append(&mut msg.to_string().as_bytes().to_owned());
87             }
88         }
89 
90         let len = data_level.len().min(buf.len());
91 
92         // 拷贝数据
93         let src = &data_level[0..len];
94         buf[0..len].copy_from_slice(src);
95 
96         // 将控制台输出日志level改回默认,否则之后都是打印特定level的日志消息
97         self.console_loglevel = LogLevel::DEFAULT;
98 
99         return Ok(data_level.len());
100     }
101 
102     /// 读取并清空缓冲区
103     pub fn read_clear(&mut self, buf: &mut [u8]) -> Result<usize, SystemError> {
104         let r = self.read_all(buf);
105         self.clear()?;
106 
107         return r;
108     }
109 
110     /// 清空缓冲区
111     pub fn clear(&mut self) -> Result<usize, SystemError> {
112         self.buffer.clear();
113         self.data.clear();
114 
115         return Ok(0);
116     }
117 
118     /// 设置输出到控制台的日志级别
119     pub fn set_level(&mut self, log_level: usize) -> Result<usize, SystemError> {
120         let log_level = log_level - 1;
121 
122         self.console_loglevel = match log_level {
123             0 => LogLevel::EMERG,
124             1 => LogLevel::ALERT,
125             2 => LogLevel::CRIT,
126             3 => LogLevel::ERR,
127             4 => LogLevel::WARN,
128             5 => LogLevel::NOTICE,
129             6 => LogLevel::INFO,
130             7 => LogLevel::DEBUG,
131             8 => LogLevel::DEFAULT,
132             _ => return Err(SystemError::EINVAL),
133         };
134 
135         return Ok(0);
136     }
137 
138     /// 将环形缓冲区的日志消息转成字节数组以拷入用户buf
139     fn tobytes(&mut self) -> usize {
140         if self.is_changed {
141             self.data.clear();
142 
143             if self.console_loglevel == LogLevel::DEFAULT {
144                 for msg in self.buffer.iter() {
145                     self.data.append(&mut msg.to_string().as_bytes().to_owned());
146                 }
147             }
148 
149             self.is_changed = false;
150         }
151 
152         return self.data.len();
153     }
154 
155     // 返回内核缓冲区所占字节数
156     pub fn data_size(&mut self) -> Result<usize, SystemError> {
157         return Ok(self.tobytes());
158     }
159 }
160