Commit daff89f3 authored by Jonathan Corbet's avatar Jonathan Corbet Committed by Linus Torvalds

[PATCH] radix-tree documentation cleanups

Documentation changes to help radix tree users avoid overrunning the tags
array.  RADIX_TREE_TAGS moves to linux/radix-tree.h and is now known as
RADIX_TREE_MAX_TAGS (Nick Piggin's idea).  Tag parameters are changed to
unsigned, and some comments are updated.
Signed-off-by: default avatarJonathan Corbet <corbet@lwn.net>
Cc: Nick Piggin <nickpiggin@yahoo.com.au>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 57070d01
...@@ -45,6 +45,8 @@ do { \ ...@@ -45,6 +45,8 @@ do { \
(root)->rnode = NULL; \ (root)->rnode = NULL; \
} while (0) } while (0)
#define RADIX_TREE_MAX_TAGS 2
int radix_tree_insert(struct radix_tree_root *, unsigned long, void *); int radix_tree_insert(struct radix_tree_root *, unsigned long, void *);
void *radix_tree_lookup(struct radix_tree_root *, unsigned long); void *radix_tree_lookup(struct radix_tree_root *, unsigned long);
void **radix_tree_lookup_slot(struct radix_tree_root *, unsigned long); void **radix_tree_lookup_slot(struct radix_tree_root *, unsigned long);
...@@ -55,15 +57,16 @@ radix_tree_gang_lookup(struct radix_tree_root *root, void **results, ...@@ -55,15 +57,16 @@ radix_tree_gang_lookup(struct radix_tree_root *root, void **results,
int radix_tree_preload(gfp_t gfp_mask); int radix_tree_preload(gfp_t gfp_mask);
void radix_tree_init(void); void radix_tree_init(void);
void *radix_tree_tag_set(struct radix_tree_root *root, void *radix_tree_tag_set(struct radix_tree_root *root,
unsigned long index, int tag); unsigned long index, unsigned int tag);
void *radix_tree_tag_clear(struct radix_tree_root *root, void *radix_tree_tag_clear(struct radix_tree_root *root,
unsigned long index, int tag); unsigned long index, unsigned int tag);
int radix_tree_tag_get(struct radix_tree_root *root, int radix_tree_tag_get(struct radix_tree_root *root,
unsigned long index, int tag); unsigned long index, unsigned int tag);
unsigned int unsigned int
radix_tree_gang_lookup_tag(struct radix_tree_root *root, void **results, radix_tree_gang_lookup_tag(struct radix_tree_root *root, void **results,
unsigned long first_index, unsigned int max_items, int tag); unsigned long first_index, unsigned int max_items,
int radix_tree_tagged(struct radix_tree_root *root, int tag); unsigned int tag);
int radix_tree_tagged(struct radix_tree_root *root, unsigned int tag);
static inline void radix_tree_preload_end(void) static inline void radix_tree_preload_end(void)
{ {
......
...@@ -37,7 +37,6 @@ ...@@ -37,7 +37,6 @@
#else #else
#define RADIX_TREE_MAP_SHIFT 3 /* For more stressful testing */ #define RADIX_TREE_MAP_SHIFT 3 /* For more stressful testing */
#endif #endif
#define RADIX_TREE_TAGS 2
#define RADIX_TREE_MAP_SIZE (1UL << RADIX_TREE_MAP_SHIFT) #define RADIX_TREE_MAP_SIZE (1UL << RADIX_TREE_MAP_SHIFT)
#define RADIX_TREE_MAP_MASK (RADIX_TREE_MAP_SIZE-1) #define RADIX_TREE_MAP_MASK (RADIX_TREE_MAP_SIZE-1)
...@@ -48,7 +47,7 @@ ...@@ -48,7 +47,7 @@
struct radix_tree_node { struct radix_tree_node {
unsigned int count; unsigned int count;
void *slots[RADIX_TREE_MAP_SIZE]; void *slots[RADIX_TREE_MAP_SIZE];
unsigned long tags[RADIX_TREE_TAGS][RADIX_TREE_TAG_LONGS]; unsigned long tags[RADIX_TREE_MAX_TAGS][RADIX_TREE_TAG_LONGS];
}; };
struct radix_tree_path { struct radix_tree_path {
...@@ -135,17 +134,20 @@ int radix_tree_preload(gfp_t gfp_mask) ...@@ -135,17 +134,20 @@ int radix_tree_preload(gfp_t gfp_mask)
return ret; return ret;
} }
static inline void tag_set(struct radix_tree_node *node, int tag, int offset) static inline void tag_set(struct radix_tree_node *node, unsigned int tag,
int offset)
{ {
__set_bit(offset, node->tags[tag]); __set_bit(offset, node->tags[tag]);
} }
static inline void tag_clear(struct radix_tree_node *node, int tag, int offset) static inline void tag_clear(struct radix_tree_node *node, unsigned int tag,
int offset)
{ {
__clear_bit(offset, node->tags[tag]); __clear_bit(offset, node->tags[tag]);
} }
static inline int tag_get(struct radix_tree_node *node, int tag, int offset) static inline int tag_get(struct radix_tree_node *node, unsigned int tag,
int offset)
{ {
return test_bit(offset, node->tags[tag]); return test_bit(offset, node->tags[tag]);
} }
...@@ -154,7 +156,7 @@ static inline int tag_get(struct radix_tree_node *node, int tag, int offset) ...@@ -154,7 +156,7 @@ static inline int tag_get(struct radix_tree_node *node, int tag, int offset)
* Returns 1 if any slot in the node has this tag set. * Returns 1 if any slot in the node has this tag set.
* Otherwise returns 0. * Otherwise returns 0.
*/ */
static inline int any_tag_set(struct radix_tree_node *node, int tag) static inline int any_tag_set(struct radix_tree_node *node, unsigned int tag)
{ {
int idx; int idx;
for (idx = 0; idx < RADIX_TREE_TAG_LONGS; idx++) { for (idx = 0; idx < RADIX_TREE_TAG_LONGS; idx++) {
...@@ -180,7 +182,7 @@ static int radix_tree_extend(struct radix_tree_root *root, unsigned long index) ...@@ -180,7 +182,7 @@ static int radix_tree_extend(struct radix_tree_root *root, unsigned long index)
{ {
struct radix_tree_node *node; struct radix_tree_node *node;
unsigned int height; unsigned int height;
char tags[RADIX_TREE_TAGS]; char tags[RADIX_TREE_MAX_TAGS];
int tag; int tag;
/* Figure out what the height should be. */ /* Figure out what the height should be. */
...@@ -197,7 +199,7 @@ static int radix_tree_extend(struct radix_tree_root *root, unsigned long index) ...@@ -197,7 +199,7 @@ static int radix_tree_extend(struct radix_tree_root *root, unsigned long index)
* Prepare the tag status of the top-level node for propagation * Prepare the tag status of the top-level node for propagation
* into the newly-pushed top-level node(s) * into the newly-pushed top-level node(s)
*/ */
for (tag = 0; tag < RADIX_TREE_TAGS; tag++) { for (tag = 0; tag < RADIX_TREE_MAX_TAGS; tag++) {
tags[tag] = 0; tags[tag] = 0;
if (any_tag_set(root->rnode, tag)) if (any_tag_set(root->rnode, tag))
tags[tag] = 1; tags[tag] = 1;
...@@ -211,7 +213,7 @@ static int radix_tree_extend(struct radix_tree_root *root, unsigned long index) ...@@ -211,7 +213,7 @@ static int radix_tree_extend(struct radix_tree_root *root, unsigned long index)
node->slots[0] = root->rnode; node->slots[0] = root->rnode;
/* Propagate the aggregated tag info into the new root */ /* Propagate the aggregated tag info into the new root */
for (tag = 0; tag < RADIX_TREE_TAGS; tag++) { for (tag = 0; tag < RADIX_TREE_MAX_TAGS; tag++) {
if (tags[tag]) if (tags[tag])
tag_set(node, tag, 0); tag_set(node, tag, 0);
} }
...@@ -349,14 +351,15 @@ EXPORT_SYMBOL(radix_tree_lookup); ...@@ -349,14 +351,15 @@ EXPORT_SYMBOL(radix_tree_lookup);
* @index: index key * @index: index key
* @tag: tag index * @tag: tag index
* *
* Set the search tag corresponging to @index in the radix tree. From * Set the search tag (which must be < RADIX_TREE_MAX_TAGS)
* corresponding to @index in the radix tree. From
* the root all the way down to the leaf node. * the root all the way down to the leaf node.
* *
* Returns the address of the tagged item. Setting a tag on a not-present * Returns the address of the tagged item. Setting a tag on a not-present
* item is a bug. * item is a bug.
*/ */
void *radix_tree_tag_set(struct radix_tree_root *root, void *radix_tree_tag_set(struct radix_tree_root *root,
unsigned long index, int tag) unsigned long index, unsigned int tag)
{ {
unsigned int height, shift; unsigned int height, shift;
struct radix_tree_node *slot; struct radix_tree_node *slot;
...@@ -390,7 +393,8 @@ EXPORT_SYMBOL(radix_tree_tag_set); ...@@ -390,7 +393,8 @@ EXPORT_SYMBOL(radix_tree_tag_set);
* @index: index key * @index: index key
* @tag: tag index * @tag: tag index
* *
* Clear the search tag corresponging to @index in the radix tree. If * Clear the search tag (which must be < RADIX_TREE_MAX_TAGS)
* corresponding to @index in the radix tree. If
* this causes the leaf node to have no tags set then clear the tag in the * this causes the leaf node to have no tags set then clear the tag in the
* next-to-leaf node, etc. * next-to-leaf node, etc.
* *
...@@ -398,7 +402,7 @@ EXPORT_SYMBOL(radix_tree_tag_set); ...@@ -398,7 +402,7 @@ EXPORT_SYMBOL(radix_tree_tag_set);
* has the same return value and semantics as radix_tree_lookup(). * has the same return value and semantics as radix_tree_lookup().
*/ */
void *radix_tree_tag_clear(struct radix_tree_root *root, void *radix_tree_tag_clear(struct radix_tree_root *root,
unsigned long index, int tag) unsigned long index, unsigned int tag)
{ {
struct radix_tree_path path[RADIX_TREE_MAX_PATH], *pathp = path; struct radix_tree_path path[RADIX_TREE_MAX_PATH], *pathp = path;
struct radix_tree_node *slot; struct radix_tree_node *slot;
...@@ -450,7 +454,7 @@ EXPORT_SYMBOL(radix_tree_tag_clear); ...@@ -450,7 +454,7 @@ EXPORT_SYMBOL(radix_tree_tag_clear);
* radix_tree_tag_get - get a tag on a radix tree node * radix_tree_tag_get - get a tag on a radix tree node
* @root: radix tree root * @root: radix tree root
* @index: index key * @index: index key
* @tag: tag index * @tag: tag index (< RADIX_TREE_MAX_TAGS)
* *
* Return values: * Return values:
* *
...@@ -459,7 +463,7 @@ EXPORT_SYMBOL(radix_tree_tag_clear); ...@@ -459,7 +463,7 @@ EXPORT_SYMBOL(radix_tree_tag_clear);
* -1: tag present, unset * -1: tag present, unset
*/ */
int radix_tree_tag_get(struct radix_tree_root *root, int radix_tree_tag_get(struct radix_tree_root *root,
unsigned long index, int tag) unsigned long index, unsigned int tag)
{ {
unsigned int height, shift; unsigned int height, shift;
struct radix_tree_node *slot; struct radix_tree_node *slot;
...@@ -592,7 +596,7 @@ EXPORT_SYMBOL(radix_tree_gang_lookup); ...@@ -592,7 +596,7 @@ EXPORT_SYMBOL(radix_tree_gang_lookup);
*/ */
static unsigned int static unsigned int
__lookup_tag(struct radix_tree_root *root, void **results, unsigned long index, __lookup_tag(struct radix_tree_root *root, void **results, unsigned long index,
unsigned int max_items, unsigned long *next_index, int tag) unsigned int max_items, unsigned long *next_index, unsigned int tag)
{ {
unsigned int nr_found = 0; unsigned int nr_found = 0;
unsigned int shift; unsigned int shift;
...@@ -646,7 +650,7 @@ __lookup_tag(struct radix_tree_root *root, void **results, unsigned long index, ...@@ -646,7 +650,7 @@ __lookup_tag(struct radix_tree_root *root, void **results, unsigned long index,
* @results: where the results of the lookup are placed * @results: where the results of the lookup are placed
* @first_index: start the lookup from this key * @first_index: start the lookup from this key
* @max_items: place up to this many items at *results * @max_items: place up to this many items at *results
* @tag: the tag index * @tag: the tag index (< RADIX_TREE_MAX_TAGS)
* *
* Performs an index-ascending scan of the tree for present items which * Performs an index-ascending scan of the tree for present items which
* have the tag indexed by @tag set. Places the items at *@results and * have the tag indexed by @tag set. Places the items at *@results and
...@@ -654,7 +658,8 @@ __lookup_tag(struct radix_tree_root *root, void **results, unsigned long index, ...@@ -654,7 +658,8 @@ __lookup_tag(struct radix_tree_root *root, void **results, unsigned long index,
*/ */
unsigned int unsigned int
radix_tree_gang_lookup_tag(struct radix_tree_root *root, void **results, radix_tree_gang_lookup_tag(struct radix_tree_root *root, void **results,
unsigned long first_index, unsigned int max_items, int tag) unsigned long first_index, unsigned int max_items,
unsigned int tag)
{ {
const unsigned long max_index = radix_tree_maxindex(root->height); const unsigned long max_index = radix_tree_maxindex(root->height);
unsigned long cur_index = first_index; unsigned long cur_index = first_index;
...@@ -716,7 +721,7 @@ void *radix_tree_delete(struct radix_tree_root *root, unsigned long index) ...@@ -716,7 +721,7 @@ void *radix_tree_delete(struct radix_tree_root *root, unsigned long index)
struct radix_tree_node *slot; struct radix_tree_node *slot;
unsigned int height, shift; unsigned int height, shift;
void *ret = NULL; void *ret = NULL;
char tags[RADIX_TREE_TAGS]; char tags[RADIX_TREE_MAX_TAGS];
int nr_cleared_tags; int nr_cleared_tags;
int tag; int tag;
int offset; int offset;
...@@ -751,7 +756,7 @@ void *radix_tree_delete(struct radix_tree_root *root, unsigned long index) ...@@ -751,7 +756,7 @@ void *radix_tree_delete(struct radix_tree_root *root, unsigned long index)
* Clear all tags associated with the just-deleted item * Clear all tags associated with the just-deleted item
*/ */
nr_cleared_tags = 0; nr_cleared_tags = 0;
for (tag = 0; tag < RADIX_TREE_TAGS; tag++) { for (tag = 0; tag < RADIX_TREE_MAX_TAGS; tag++) {
tags[tag] = 1; tags[tag] = 1;
if (tag_get(pathp->node, tag, pathp->offset)) { if (tag_get(pathp->node, tag, pathp->offset)) {
tag_clear(pathp->node, tag, pathp->offset); tag_clear(pathp->node, tag, pathp->offset);
...@@ -763,7 +768,7 @@ void *radix_tree_delete(struct radix_tree_root *root, unsigned long index) ...@@ -763,7 +768,7 @@ void *radix_tree_delete(struct radix_tree_root *root, unsigned long index)
} }
for (pathp--; nr_cleared_tags && pathp->node; pathp--) { for (pathp--; nr_cleared_tags && pathp->node; pathp--) {
for (tag = 0; tag < RADIX_TREE_TAGS; tag++) { for (tag = 0; tag < RADIX_TREE_MAX_TAGS; tag++) {
if (tags[tag]) if (tags[tag])
continue; continue;
...@@ -801,7 +806,7 @@ EXPORT_SYMBOL(radix_tree_delete); ...@@ -801,7 +806,7 @@ EXPORT_SYMBOL(radix_tree_delete);
* @root: radix tree root * @root: radix tree root
* @tag: tag to test * @tag: tag to test
*/ */
int radix_tree_tagged(struct radix_tree_root *root, int tag) int radix_tree_tagged(struct radix_tree_root *root, unsigned int tag)
{ {
struct radix_tree_node *rnode; struct radix_tree_node *rnode;
rnode = root->rnode; rnode = root->rnode;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment