summaryrefslogtreecommitdiff
path: root/include/linux
diff options
context:
space:
mode:
authorAndrew Morton <akpm@digeo.com>2003-01-05 03:51:21 -0800
committerLinus Torvalds <torvalds@home.transmeta.com>2003-01-05 03:51:21 -0800
commit9fb6fde975800f1275d466775913b175cd039044 (patch)
tree13c504c2db4b116ec88359237cd0874a7c561f25 /include/linux
parentaaf2ef19a8230e93cfca948738bc3990a589b8fb (diff)
[PATCH] infrastructure for handling radix_tree_node allocation
radix_tree_node_alloc() uses GFP_ATOMIC, under spinlocking. If the allocation fails then userspace sees ENOMEM and application failure occurs. A single add_to_page_cache() will require up to six radix_tree_nodes on 32-bit machines, twice this on 64-bit machines (quadruple the worst-case storage on 64-bit). My approach to solving this problem is to create a per-cpu pool of preallocated radix_tree_nodes, private to the radix-tree code. The radix-tree user will call the new radix-tree API function radix_tree_preload() to ensure that this pool has sufficient nodes to cover the worst-case. radix_tree_preload() should be called outside locks, with GFP_KERNEL so that it can run page reclaim. If it succeeds, radix_tree_preload() will return with preemption disabled so that the per-cpu radix_tree_node pool is protected. The user must call radix_tree_preload_end() to terminate the transaction. In the common case, the per-cpu pools will never be touched: radix_tree_insert() will only dip into the pool if kmem_cache_alloc() fails. The pools will remain full at all times. This is to optimise the fastpath - it is just a few instructions. This patch also removes the now-unneeded radix-tree mempool. This saves 130 kbytes of permanently allocated kernel memory. 260k on 64-bit platforms.
Diffstat (limited to 'include/linux')
-rw-r--r--include/linux/radix-tree.h8
1 files changed, 8 insertions, 0 deletions
diff --git a/include/linux/radix-tree.h b/include/linux/radix-tree.h
index 4e58eb79abeb..f4a78d52b5ce 100644
--- a/include/linux/radix-tree.h
+++ b/include/linux/radix-tree.h
@@ -19,6 +19,8 @@
#ifndef _LINUX_RADIX_TREE_H
#define _LINUX_RADIX_TREE_H
+#include <linux/preempt.h>
+
struct radix_tree_node;
struct radix_tree_root {
@@ -45,5 +47,11 @@ extern int radix_tree_delete(struct radix_tree_root *, unsigned long);
extern unsigned int
radix_tree_gang_lookup(struct radix_tree_root *root, void **results,
unsigned long first_index, unsigned int max_items);
+int radix_tree_preload(int gfp_mask);
+
+static inline void radix_tree_preload_end(void)
+{
+ preempt_enable();
+}
#endif /* _LINUX_RADIX_TREE_H */