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