nydus_utils/
inode_bitmap.rs1use std::collections::BTreeMap;
7use std::fmt::{Debug, Display, Formatter};
8use std::sync::atomic::{AtomicU64, Ordering};
9use std::sync::RwLock;
10
11#[derive(Default)]
12pub struct InodeBitmap {
13 map: RwLock<BTreeMap<u64, AtomicU64>>,
14}
15
16impl Debug for InodeBitmap {
17 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
18 f.write_str(self.to_string().as_str())
19 }
20}
21
22impl Display for InodeBitmap {
23 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
24 f.write_str(
25 serde_json::json!({"inode_range": self.bitmap_to_array()})
26 .to_string()
27 .as_str(),
28 )
29 }
30}
31
32impl InodeBitmap {
33 pub fn new() -> Self {
34 Self::default()
35 }
36
37 #[inline(always)]
38 fn get_index_and_mask(ino: u64) -> (u64, u64) {
39 (ino >> 6, 1_u64 << (ino & 0x3f_u64))
40 }
41
42 #[inline(always)]
43 fn range_to_vec(start: u64, end: u64) -> Vec<u64> {
44 if start == end {
45 vec![start]
46 } else {
47 vec![start, end]
48 }
49 }
50
51 pub fn set(&self, ino: u64) {
52 let (index, mask) = Self::get_index_and_mask(ino);
53
54 let m = self.map.read().unwrap();
55 if let Some(v) = m.get(&index) {
56 v.fetch_or(mask, Ordering::Relaxed);
57 return;
58 }
59 drop(m);
60
61 let mut m = self.map.write().unwrap();
62 m.entry(index)
63 .or_insert_with(|| AtomicU64::new(0))
64 .fetch_or(mask, Ordering::Relaxed);
65 }
66
67 pub fn is_set(&self, ino: u64) -> bool {
68 let (index, mask) = InodeBitmap::get_index_and_mask(ino);
69 self.map
70 .read()
71 .unwrap()
72 .get(&index)
73 .is_some_and(|v| v.load(Ordering::Relaxed) & mask != 0)
74 }
75
76 pub fn clear(&self, ino: u64) {
77 let (index, mask) = InodeBitmap::get_index_and_mask(ino);
78 let m = self.map.read().unwrap();
79
80 if let Some(v) = m.get(&index) {
81 v.fetch_and(!mask, Ordering::Relaxed);
82 }
83 }
84
85 pub fn clear_all(&self) {
86 let m = self.map.read().unwrap();
87
88 for it in m.values() {
89 it.store(0_u64, Ordering::Relaxed);
90 }
91 }
92
93 fn bitmap_to_vec(&self, load: fn(&AtomicU64) -> u64) -> Vec<Vec<u64>> {
95 let m = self.map.read().unwrap();
96 let mut ret: Vec<Vec<u64>> = Vec::new();
97 let mut start: Option<u64> = None;
98 let mut last: u64 = 0;
100
101 for it in m.iter() {
102 let base = it.0 << 6;
103 let mut v = load(it.1);
104
105 while v != 0 {
106 let ino = base + v.trailing_zeros() as u64;
108 v &= v - 1;
109 start = match start {
110 None => Some(ino),
111 Some(s) => {
112 if ino != last + 1 {
113 ret.push(InodeBitmap::range_to_vec(s, last));
114 Some(ino)
115 } else {
116 Some(s)
117 }
118 }
119 };
120 last = ino;
121 }
122 }
123 if let Some(s) = start {
124 ret.push(InodeBitmap::range_to_vec(s, last));
125 }
126
127 ret
128 }
129
130 pub fn bitmap_to_array(&self) -> Vec<Vec<u64>> {
131 self.bitmap_to_vec(|v| v.load(Ordering::Relaxed))
132 }
133
134 pub fn bitmap_to_array_and_clear(&self) -> Vec<Vec<u64>> {
135 self.bitmap_to_vec(|v| v.fetch_and(0_u64, Ordering::Relaxed))
136 }
137}
138
139#[cfg(test)]
140mod tests {
141 use super::*;
142
143 #[test]
144 fn test_inode_bitmap() {
145 let empty: Vec<Vec<u64>> = Vec::new();
146 let m = InodeBitmap::new();
147 m.set(1);
148 m.set(2);
149 m.set(5);
150 assert_eq!(m.bitmap_to_array(), [vec![1, 2], vec![5]]);
151
152 assert!(m.is_set(2));
153 m.clear(2);
154 assert!(!m.is_set(2));
155 assert_eq!(m.bitmap_to_array(), [[1], [5]]);
156
157 m.set(65);
158 m.set(66);
159 m.set(4000);
160 m.set(40001);
161 m.set(40002);
162 m.set(40003);
163 assert_eq!(
164 m.bitmap_to_array(),
165 [
166 vec![1],
167 vec![5],
168 vec![65, 66],
169 vec![4000],
170 vec![40001, 40003]
171 ]
172 );
173
174 m.clear_all();
175 assert_eq!(m.bitmap_to_array(), empty);
176
177 m.set(65);
178 m.set(40001);
179 assert_eq!(m.bitmap_to_array(), [vec![65], vec![40001]]);
180
181 for i in 0..100000 {
182 m.set(i);
183 }
184 m.set(100002);
185 assert_eq!(
186 m.bitmap_to_array_and_clear(),
187 [vec![0, 99999], vec![100002]]
188 );
189 assert!(!m.is_set(9000));
190 assert_eq!(m.bitmap_to_array(), empty);
191 }
192}