aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/kref.c97
-rw-r--r--lib/prio_tree.c484
2 files changed, 581 insertions, 0 deletions
diff --git a/lib/kref.c b/lib/kref.c
new file mode 100644
index 00000000000..3efb882b11d
--- /dev/null
+++ b/lib/kref.c
@@ -0,0 +1,97 @@
1/*
2 * kref.c - library routines for handling generic reference counted objects
3 *
4 * Copyright (C) 2004 Greg Kroah-Hartman <greg@kroah.com>
5 * Copyright (C) 2004 IBM Corp.
6 *
7 * based on lib/kobject.c which was:
8 * Copyright (C) 2002-2003 Patrick Mochel <mochel@osdl.org>
9 *
10 * This file is released under the GPLv2.
11 *
12 */
13
14#include <linux/kref.h>
15#include <linux/module.h>
16#include <linux/slab.h>
17
18/**
19 * kref_init - initialize object.
20 * @kref: object in question.
21 */
22void kref_init(struct kref *kref)
23{
24 atomic_set(&kref->refcount, 1);
25 smp_mb();
26}
27
28/**
29 * kref_get - increment refcount for object.
30 * @kref: object.
31 */
32void kref_get(struct kref *kref)
33{
34 WARN_ON(!atomic_read(&kref->refcount));
35 atomic_inc(&kref->refcount);
36 smp_mb__after_atomic_inc();
37}
38
39/**
40 * kref_put - decrement refcount for object.
41 * @kref: object.
42 * @release: pointer to the function that will clean up the object when the
43 * last reference to the object is released.
44 * This pointer is required, and it is not acceptable to pass kfree
45 * in as this function.
46 *
47 * Decrement the refcount, and if 0, call release().
48 * Return 1 if the object was removed, otherwise return 0. Beware, if this
49 * function returns 0, you still can not count on the kref from remaining in
50 * memory. Only use the return value if you want to see if the kref is now
51 * gone, not present.
52 */
53int kref_put(struct kref *kref, void (*release)(struct kref *kref))
54{
55 WARN_ON(release == NULL);
56 WARN_ON(release == (void (*)(struct kref *))kfree);
57
58 if (atomic_dec_and_test(&kref->refcount)) {
59 release(kref);
60 return 1;
61 }
62 return 0;
63}
64
65
66/**
67 * kref_sub - subtract a number of refcounts for object.
68 * @kref: object.
69 * @count: Number of recounts to subtract.
70 * @release: pointer to the function that will clean up the object when the
71 * last reference to the object is released.
72 * This pointer is required, and it is not acceptable to pass kfree
73 * in as this function.
74 *
75 * Subtract @count from the refcount, and if 0, call release().
76 * Return 1 if the object was removed, otherwise return 0. Beware, if this
77 * function returns 0, you still can not count on the kref from remaining in
78 * memory. Only use the return value if you want to see if the kref is now
79 * gone, not present.
80 */
81int kref_sub(struct kref *kref, unsigned int count,
82 void (*release)(struct kref *kref))
83{
84 WARN_ON(release == NULL);
85 WARN_ON(release == (void (*)(struct kref *))kfree);
86
87 if (atomic_sub_and_test((int) count, &kref->refcount)) {
88 release(kref);
89 return 1;
90 }
91 return 0;
92}
93
94EXPORT_SYMBOL(kref_init);
95EXPORT_SYMBOL(kref_get);
96EXPORT_SYMBOL(kref_put);
97EXPORT_SYMBOL(kref_sub);
diff --git a/lib/prio_tree.c b/lib/prio_tree.c
new file mode 100644
index 00000000000..ccfd850b0de
--- /dev/null
+++ b/lib/prio_tree.c
@@ -0,0 +1,484 @@
1/*
2 * lib/prio_tree.c - priority search tree
3 *
4 * Copyright (C) 2004, Rajesh Venkatasubramanian <vrajesh@umich.edu>
5 *
6 * This file is released under the GPL v2.
7 *
8 * Based on the radix priority search tree proposed by Edward M. McCreight
9 * SIAM Journal of Computing, vol. 14, no.2, pages 257-276, May 1985
10 *
11 * 02Feb2004 Initial version
12 */
13
14#include <linux/init.h>
15#include <linux/mm.h>
16#include <linux/prio_tree.h>
17
18/*
19 * A clever mix of heap and radix trees forms a radix priority search tree (PST)
20 * which is useful for storing intervals, e.g, we can consider a vma as a closed
21 * interval of file pages [offset_begin, offset_end], and store all vmas that
22 * map a file in a PST. Then, using the PST, we can answer a stabbing query,
23 * i.e., selecting a set of stored intervals (vmas) that overlap with (map) a
24 * given input interval X (a set of consecutive file pages), in "O(log n + m)"
25 * time where 'log n' is the height of the PST, and 'm' is the number of stored
26 * intervals (vmas) that overlap (map) with the input interval X (the set of
27 * consecutive file pages).
28 *
29 * In our implementation, we store closed intervals of the form [radix_index,
30 * heap_index]. We assume that always radix_index <= heap_index. McCreight's PST
31 * is designed for storing intervals with unique radix indices, i.e., each
32 * interval have different radix_index. However, this limitation can be easily
33 * overcome by using the size, i.e., heap_index - radix_index, as part of the
34 * index, so we index the tree using [(radix_index,size), heap_index].
35 *
36 * When the above-mentioned indexing scheme is used, theoretically, in a 32 bit
37 * machine, the maximum height of a PST can be 64. We can use a balanced version
38 * of the priority search tree to optimize the tree height, but the balanced
39 * tree proposed by McCreight is too complex and memory-hungry for our purpose.
40 */
41
42/*
43 * The following macros are used for implementing prio_tree for i_mmap
44 */
45
46#define RADIX_INDEX(vma) ((vma)->vm_pgoff)
47#define VMA_SIZE(vma) (((vma)->vm_end - (vma)->vm_start) >> PAGE_SHIFT)
48/* avoid overflow */
49#define HEAP_INDEX(vma) ((vma)->vm_pgoff + (VMA_SIZE(vma) - 1))
50
51
52static void get_index(const struct prio_tree_root *root,
53 const struct prio_tree_node *node,
54 unsigned long *radix, unsigned long *heap)
55{
56 if (root->raw) {
57 struct vm_area_struct *vma = prio_tree_entry(
58 node, struct vm_area_struct, shared.prio_tree_node);
59
60 *radix = RADIX_INDEX(vma);
61 *heap = HEAP_INDEX(vma);
62 }
63 else {
64 *radix = node->start;
65 *heap = node->last;
66 }
67}
68
69static unsigned long index_bits_to_maxindex[BITS_PER_LONG];
70
71void __init prio_tree_init(void)
72{
73 unsigned int i;
74
75 for (i = 0; i < ARRAY_SIZE(index_bits_to_maxindex) - 1; i++)
76 index_bits_to_maxindex[i] = (1UL << (i + 1)) - 1;
77 index_bits_to_maxindex[ARRAY_SIZE(index_bits_to_maxindex) - 1] = ~0UL;
78}
79
80/*
81 * Maximum heap_index that can be stored in a PST with index_bits bits
82 */
83static inline unsigned long prio_tree_maxindex(unsigned int bits)
84{
85 return index_bits_to_maxindex[bits - 1];
86}
87
88/*
89 * Extend a priority search tree so that it can store a node with heap_index
90 * max_heap_index. In the worst case, this algorithm takes O((log n)^2).
91 * However, this function is used rarely and the common case performance is
92 * not bad.
93 */
94static struct prio_tree_node *prio_tree_expand(struct prio_tree_root *root,
95 struct prio_tree_node *node, unsigned long max_heap_index)
96{
97 struct prio_tree_node *first = NULL, *prev, *last = NULL;
98
99 if (max_heap_index > prio_tree_maxindex(root->index_bits))
100 root->index_bits++;
101
102 while (max_heap_index > prio_tree_maxindex(root->index_bits)) {
103 root->index_bits++;
104
105 if (prio_tree_empty(root))
106 continue;
107
108 if (first == NULL) {
109 first = root->prio_tree_node;
110 prio_tree_remove(root, root->prio_tree_node);
111 INIT_PRIO_TREE_NODE(first);
112 last = first;
113 } else {
114 prev = last;
115 last = root->prio_tree_node;
116 prio_tree_remove(root, root->prio_tree_node);
117 INIT_PRIO_TREE_NODE(last);
118 prev->left = last;
119 last->parent = prev;
120 }
121 }
122
123 INIT_PRIO_TREE_NODE(node);
124
125 if (first) {
126 node->left = first;
127 first->parent = node;
128 } else
129 last = node;
130
131 if (!prio_tree_empty(root)) {
132 last->left = root->prio_tree_node;
133 last->left->parent = last;
134 }