tree.rs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488
  1. // SPDX-License-Identifier: GPL-2.0
  2. // Copyright (C) 2025 Google LLC.
  3. use kernel::{
  4. page::PAGE_SIZE,
  5. prelude::*,
  6. rbtree::{RBTree, RBTreeNode, RBTreeNodeReservation},
  7. seq_file::SeqFile,
  8. seq_print,
  9. task::Pid,
  10. };
  11. use crate::range_alloc::{DescriptorState, FreedRange, Range};
  12. /// Keeps track of allocations in a process' mmap.
  13. ///
  14. /// Each process has an mmap where the data for incoming transactions will be placed. This struct
  15. /// keeps track of allocations made in the mmap. For each allocation, we store a descriptor that
  16. /// has metadata related to the allocation. We also keep track of available free space.
  17. pub(super) struct TreeRangeAllocator<T> {
  18. /// This collection contains descriptors for *both* ranges containing an allocation, *and* free
  19. /// ranges between allocations. The free ranges get merged, so there are never two free ranges
  20. /// next to each other.
  21. tree: RBTree<usize, Descriptor<T>>,
  22. /// Contains an entry for every free range in `self.tree`. This tree sorts the ranges by size,
  23. /// letting us look up the smallest range whose size is at least some lower bound.
  24. free_tree: RBTree<FreeKey, ()>,
  25. size: usize,
  26. free_oneway_space: usize,
  27. }
  28. impl<T> TreeRangeAllocator<T> {
  29. pub(crate) fn from_array(
  30. size: usize,
  31. ranges: &mut KVec<Range<T>>,
  32. alloc: &mut FromArrayAllocs<T>,
  33. ) -> Self {
  34. let mut tree = TreeRangeAllocator {
  35. tree: RBTree::new(),
  36. free_tree: RBTree::new(),
  37. size,
  38. free_oneway_space: size / 2,
  39. };
  40. let mut free_offset = 0;
  41. for range in ranges.drain_all() {
  42. let free_size = range.offset - free_offset;
  43. if free_size > 0 {
  44. let free_node = alloc.free_tree.pop().unwrap();
  45. tree.free_tree
  46. .insert(free_node.into_node((free_size, free_offset), ()));
  47. let tree_node = alloc.tree.pop().unwrap();
  48. tree.tree.insert(
  49. tree_node.into_node(free_offset, Descriptor::new(free_offset, free_size)),
  50. );
  51. }
  52. free_offset = range.endpoint();
  53. if range.state.is_oneway() {
  54. tree.free_oneway_space = tree.free_oneway_space.saturating_sub(range.size);
  55. }
  56. let free_res = alloc.free_tree.pop().unwrap();
  57. let tree_node = alloc.tree.pop().unwrap();
  58. let mut desc = Descriptor::new(range.offset, range.size);
  59. desc.state = Some((range.state, free_res));
  60. tree.tree.insert(tree_node.into_node(range.offset, desc));
  61. }
  62. // After the last range, we may need a free range.
  63. if free_offset < size {
  64. let free_size = size - free_offset;
  65. let free_node = alloc.free_tree.pop().unwrap();
  66. tree.free_tree
  67. .insert(free_node.into_node((free_size, free_offset), ()));
  68. let tree_node = alloc.tree.pop().unwrap();
  69. tree.tree
  70. .insert(tree_node.into_node(free_offset, Descriptor::new(free_offset, free_size)));
  71. }
  72. tree
  73. }
  74. pub(crate) fn is_empty(&self) -> bool {
  75. let mut tree_iter = self.tree.values();
  76. // There's always at least one range, because index zero is either the start of a free or
  77. // allocated range.
  78. let first_value = tree_iter.next().unwrap();
  79. if tree_iter.next().is_some() {
  80. // There are never two free ranges next to each other, so if there is more than one
  81. // descriptor, then at least one of them must hold an allocated range.
  82. return false;
  83. }
  84. // There is only one descriptor. Return true if it is for a free range.
  85. first_value.state.is_none()
  86. }
  87. pub(crate) fn total_size(&self) -> usize {
  88. self.size
  89. }
  90. pub(crate) fn free_oneway_space(&self) -> usize {
  91. self.free_oneway_space
  92. }
  93. pub(crate) fn count_buffers(&self) -> usize {
  94. self.tree
  95. .values()
  96. .filter(|desc| desc.state.is_some())
  97. .count()
  98. }
  99. pub(crate) fn debug_print(&self, m: &SeqFile) -> Result<()> {
  100. for desc in self.tree.values() {
  101. let state = match &desc.state {
  102. Some(state) => &state.0,
  103. None => continue,
  104. };
  105. seq_print!(
  106. m,
  107. " buffer: {} size {} pid {}",
  108. desc.offset,
  109. desc.size,
  110. state.pid(),
  111. );
  112. if state.is_oneway() {
  113. seq_print!(m, " oneway");
  114. }
  115. match state {
  116. DescriptorState::Reserved(_res) => {
  117. seq_print!(m, " reserved\n");
  118. }
  119. DescriptorState::Allocated(_alloc) => {
  120. seq_print!(m, " allocated\n");
  121. }
  122. }
  123. }
  124. Ok(())
  125. }
  126. fn find_best_match(&mut self, size: usize) -> Option<&mut Descriptor<T>> {
  127. let free_cursor = self.free_tree.cursor_lower_bound(&(size, 0))?;
  128. let ((_, offset), ()) = free_cursor.current();
  129. self.tree.get_mut(offset)
  130. }
  131. /// Try to reserve a new buffer, using the provided allocation if necessary.
  132. pub(crate) fn reserve_new(
  133. &mut self,
  134. debug_id: usize,
  135. size: usize,
  136. is_oneway: bool,
  137. pid: Pid,
  138. alloc: ReserveNewTreeAlloc<T>,
  139. ) -> Result<(usize, bool)> {
  140. // Compute new value of free_oneway_space, which is set only on success.
  141. let new_oneway_space = if is_oneway {
  142. match self.free_oneway_space.checked_sub(size) {
  143. Some(new_oneway_space) => new_oneway_space,
  144. None => return Err(ENOSPC),
  145. }
  146. } else {
  147. self.free_oneway_space
  148. };
  149. let (found_size, found_off, tree_node, free_tree_node) = match self.find_best_match(size) {
  150. None => {
  151. pr_warn!("ENOSPC from range_alloc.reserve_new - size: {}", size);
  152. return Err(ENOSPC);
  153. }
  154. Some(desc) => {
  155. let found_size = desc.size;
  156. let found_offset = desc.offset;
  157. // In case we need to break up the descriptor
  158. let new_desc = Descriptor::new(found_offset + size, found_size - size);
  159. let (tree_node, free_tree_node, desc_node_res) = alloc.initialize(new_desc);
  160. desc.state = Some((
  161. DescriptorState::new(is_oneway, debug_id, pid),
  162. desc_node_res,
  163. ));
  164. desc.size = size;
  165. (found_size, found_offset, tree_node, free_tree_node)
  166. }
  167. };
  168. self.free_oneway_space = new_oneway_space;
  169. self.free_tree.remove(&(found_size, found_off));
  170. if found_size != size {
  171. self.tree.insert(tree_node);
  172. self.free_tree.insert(free_tree_node);
  173. }
  174. // Start detecting spammers once we have less than 20%
  175. // of async space left (which is less than 10% of total
  176. // buffer size).
  177. //
  178. // (This will short-circuit, so `low_oneway_space` is
  179. // only called when necessary.)
  180. let oneway_spam_detected =
  181. is_oneway && new_oneway_space < self.size / 10 && self.low_oneway_space(pid);
  182. Ok((found_off, oneway_spam_detected))
  183. }
  184. pub(crate) fn reservation_abort(&mut self, offset: usize) -> Result<FreedRange> {
  185. let mut cursor = self.tree.cursor_lower_bound_mut(&offset).ok_or_else(|| {
  186. pr_warn!(
  187. "EINVAL from range_alloc.reservation_abort - offset: {}",
  188. offset
  189. );
  190. EINVAL
  191. })?;
  192. let (_, desc) = cursor.current_mut();
  193. if desc.offset != offset {
  194. pr_warn!(
  195. "EINVAL from range_alloc.reservation_abort - offset: {}",
  196. offset
  197. );
  198. return Err(EINVAL);
  199. }
  200. let (reservation, free_node_res) = desc.try_change_state(|state| match state {
  201. Some((DescriptorState::Reserved(reservation), free_node_res)) => {
  202. (None, Ok((reservation, free_node_res)))
  203. }
  204. None => {
  205. pr_warn!(
  206. "EINVAL from range_alloc.reservation_abort - offset: {}",
  207. offset
  208. );
  209. (None, Err(EINVAL))
  210. }
  211. allocated => {
  212. pr_warn!(
  213. "EPERM from range_alloc.reservation_abort - offset: {}",
  214. offset
  215. );
  216. (allocated, Err(EPERM))
  217. }
  218. })?;
  219. let mut size = desc.size;
  220. let mut offset = desc.offset;
  221. let free_oneway_space_add = if reservation.is_oneway { size } else { 0 };
  222. self.free_oneway_space += free_oneway_space_add;
  223. let mut freed_range = FreedRange::interior_pages(offset, size);
  224. // Compute how large the next free region needs to be to include one more page in
  225. // the newly freed range.
  226. let add_next_page_needed = match (offset + size) % PAGE_SIZE {
  227. 0 => usize::MAX,
  228. unalign => PAGE_SIZE - unalign,
  229. };
  230. // Compute how large the previous free region needs to be to include one more page
  231. // in the newly freed range.
  232. let add_prev_page_needed = match offset % PAGE_SIZE {
  233. 0 => usize::MAX,
  234. unalign => unalign,
  235. };
  236. // Merge next into current if next is free
  237. let remove_next = match cursor.peek_next() {
  238. Some((_, next)) if next.state.is_none() => {
  239. if next.size >= add_next_page_needed {
  240. freed_range.end_page_idx += 1;
  241. }
  242. self.free_tree.remove(&(next.size, next.offset));
  243. size += next.size;
  244. true
  245. }
  246. _ => false,
  247. };
  248. if remove_next {
  249. let (_, desc) = cursor.current_mut();
  250. desc.size = size;
  251. cursor.remove_next();
  252. }
  253. // Merge current into prev if prev is free
  254. match cursor.peek_prev_mut() {
  255. Some((_, prev)) if prev.state.is_none() => {
  256. if prev.size >= add_prev_page_needed {
  257. freed_range.start_page_idx -= 1;
  258. }
  259. // merge previous with current, remove current
  260. self.free_tree.remove(&(prev.size, prev.offset));
  261. offset = prev.offset;
  262. size += prev.size;
  263. prev.size = size;
  264. cursor.remove_current();
  265. }
  266. _ => {}
  267. };
  268. self.free_tree
  269. .insert(free_node_res.into_node((size, offset), ()));
  270. Ok(freed_range)
  271. }
  272. pub(crate) fn reservation_commit(&mut self, offset: usize, data: &mut Option<T>) -> Result {
  273. let desc = self.tree.get_mut(&offset).ok_or(ENOENT)?;
  274. desc.try_change_state(|state| match state {
  275. Some((DescriptorState::Reserved(reservation), free_node_res)) => (
  276. Some((
  277. DescriptorState::Allocated(reservation.allocate(data.take())),
  278. free_node_res,
  279. )),
  280. Ok(()),
  281. ),
  282. other => (other, Err(ENOENT)),
  283. })
  284. }
  285. /// Takes an entry at the given offset from [`DescriptorState::Allocated`] to
  286. /// [`DescriptorState::Reserved`].
  287. ///
  288. /// Returns the size of the existing entry and the data associated with it.
  289. pub(crate) fn reserve_existing(&mut self, offset: usize) -> Result<(usize, usize, Option<T>)> {
  290. let desc = self.tree.get_mut(&offset).ok_or_else(|| {
  291. pr_warn!(
  292. "ENOENT from range_alloc.reserve_existing - offset: {}",
  293. offset
  294. );
  295. ENOENT
  296. })?;
  297. let (debug_id, data) = desc.try_change_state(|state| match state {
  298. Some((DescriptorState::Allocated(allocation), free_node_res)) => {
  299. let (reservation, data) = allocation.deallocate();
  300. let debug_id = reservation.debug_id;
  301. (
  302. Some((DescriptorState::Reserved(reservation), free_node_res)),
  303. Ok((debug_id, data)),
  304. )
  305. }
  306. other => {
  307. pr_warn!(
  308. "ENOENT from range_alloc.reserve_existing - offset: {}",
  309. offset
  310. );
  311. (other, Err(ENOENT))
  312. }
  313. })?;
  314. Ok((desc.size, debug_id, data))
  315. }
  316. /// Call the provided callback at every allocated region.
  317. ///
  318. /// This destroys the range allocator. Used only during shutdown.
  319. pub(crate) fn take_for_each<F: Fn(usize, usize, usize, Option<T>)>(&mut self, callback: F) {
  320. for (_, desc) in self.tree.iter_mut() {
  321. if let Some((DescriptorState::Allocated(allocation), _)) = &mut desc.state {
  322. callback(
  323. desc.offset,
  324. desc.size,
  325. allocation.debug_id(),
  326. allocation.take(),
  327. );
  328. }
  329. }
  330. }
  331. /// Find the amount and size of buffers allocated by the current caller.
  332. ///
  333. /// The idea is that once we cross the threshold, whoever is responsible
  334. /// for the low async space is likely to try to send another async transaction,
  335. /// and at some point we'll catch them in the act. This is more efficient
  336. /// than keeping a map per pid.
  337. fn low_oneway_space(&self, calling_pid: Pid) -> bool {
  338. let mut total_alloc_size = 0;
  339. let mut num_buffers = 0;
  340. for (_, desc) in self.tree.iter() {
  341. if let Some((state, _)) = &desc.state {
  342. if state.is_oneway() && state.pid() == calling_pid {
  343. total_alloc_size += desc.size;
  344. num_buffers += 1;
  345. }
  346. }
  347. }
  348. // Warn if this pid has more than 50 transactions, or more than 50% of
  349. // async space (which is 25% of total buffer size). Oneway spam is only
  350. // detected when the threshold is exceeded.
  351. num_buffers > 50 || total_alloc_size > self.size / 4
  352. }
  353. }
  354. type TreeDescriptorState<T> = (DescriptorState<T>, FreeNodeRes);
  355. struct Descriptor<T> {
  356. size: usize,
  357. offset: usize,
  358. state: Option<TreeDescriptorState<T>>,
  359. }
  360. impl<T> Descriptor<T> {
  361. fn new(offset: usize, size: usize) -> Self {
  362. Self {
  363. size,
  364. offset,
  365. state: None,
  366. }
  367. }
  368. fn try_change_state<F, Data>(&mut self, f: F) -> Result<Data>
  369. where
  370. F: FnOnce(Option<TreeDescriptorState<T>>) -> (Option<TreeDescriptorState<T>>, Result<Data>),
  371. {
  372. let (new_state, result) = f(self.state.take());
  373. self.state = new_state;
  374. result
  375. }
  376. }
  377. // (Descriptor.size, Descriptor.offset)
  378. type FreeKey = (usize, usize);
  379. type FreeNodeRes = RBTreeNodeReservation<FreeKey, ()>;
  380. /// An allocation for use by `reserve_new`.
  381. pub(crate) struct ReserveNewTreeAlloc<T> {
  382. tree_node_res: RBTreeNodeReservation<usize, Descriptor<T>>,
  383. free_tree_node_res: FreeNodeRes,
  384. desc_node_res: FreeNodeRes,
  385. }
  386. impl<T> ReserveNewTreeAlloc<T> {
  387. pub(crate) fn try_new() -> Result<Self> {
  388. let tree_node_res = RBTreeNodeReservation::new(GFP_KERNEL)?;
  389. let free_tree_node_res = RBTreeNodeReservation::new(GFP_KERNEL)?;
  390. let desc_node_res = RBTreeNodeReservation::new(GFP_KERNEL)?;
  391. Ok(Self {
  392. tree_node_res,
  393. free_tree_node_res,
  394. desc_node_res,
  395. })
  396. }
  397. fn initialize(
  398. self,
  399. desc: Descriptor<T>,
  400. ) -> (
  401. RBTreeNode<usize, Descriptor<T>>,
  402. RBTreeNode<FreeKey, ()>,
  403. FreeNodeRes,
  404. ) {
  405. let size = desc.size;
  406. let offset = desc.offset;
  407. (
  408. self.tree_node_res.into_node(offset, desc),
  409. self.free_tree_node_res.into_node((size, offset), ()),
  410. self.desc_node_res,
  411. )
  412. }
  413. }
  414. /// An allocation for creating a tree from an `ArrayRangeAllocator`.
  415. pub(crate) struct FromArrayAllocs<T> {
  416. tree: KVec<RBTreeNodeReservation<usize, Descriptor<T>>>,
  417. free_tree: KVec<RBTreeNodeReservation<FreeKey, ()>>,
  418. }
  419. impl<T> FromArrayAllocs<T> {
  420. pub(crate) fn try_new(len: usize) -> Result<Self> {
  421. let num_descriptors = 2 * len + 1;
  422. let mut tree = KVec::with_capacity(num_descriptors, GFP_KERNEL)?;
  423. for _ in 0..num_descriptors {
  424. tree.push(RBTreeNodeReservation::new(GFP_KERNEL)?, GFP_KERNEL)?;
  425. }
  426. let mut free_tree = KVec::with_capacity(num_descriptors, GFP_KERNEL)?;
  427. for _ in 0..num_descriptors {
  428. free_tree.push(RBTreeNodeReservation::new(GFP_KERNEL)?, GFP_KERNEL)?;
  429. }
  430. Ok(Self { tree, free_tree })
  431. }
  432. }