Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 374864
b: refs/heads/master
c: f7f82b8
h: refs/heads/master
v: v3
  • Loading branch information
Wang Shilong authored and Josef Bacik committed May 6, 2013
1 parent 664ad5e commit e85a705
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 9 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: c2c71324ecb471c932bc1ff59e46ffcf82f274fc
refs/heads/master: f7f82b81d2c297a5864dcfd0a205917d3e753aba
58 changes: 50 additions & 8 deletions trunk/fs/btrfs/ulist.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ void ulist_init(struct ulist *ulist)
ulist->nnodes = 0;
ulist->nodes = ulist->int_nodes;
ulist->nodes_alloced = ULIST_SIZE;
ulist->root = RB_ROOT;
}
EXPORT_SYMBOL(ulist_init);

Expand All @@ -72,6 +73,7 @@ void ulist_fini(struct ulist *ulist)
if (ulist->nodes_alloced > ULIST_SIZE)
kfree(ulist->nodes);
ulist->nodes_alloced = 0; /* in case ulist_fini is called twice */
ulist->root = RB_ROOT;
}
EXPORT_SYMBOL(ulist_fini);

Expand Down Expand Up @@ -123,6 +125,45 @@ void ulist_free(struct ulist *ulist)
}
EXPORT_SYMBOL(ulist_free);

static struct ulist_node *ulist_rbtree_search(struct ulist *ulist, u64 val)
{
struct rb_node *n = ulist->root.rb_node;
struct ulist_node *u = NULL;

while (n) {
u = rb_entry(n, struct ulist_node, rb_node);
if (u->val < val)
n = n->rb_right;
else if (u->val > val)
n = n->rb_left;
else
return u;
}
return NULL;
}

static int ulist_rbtree_insert(struct ulist *ulist, struct ulist_node *ins)
{
struct rb_node **p = &ulist->root.rb_node;
struct rb_node *parent = NULL;
struct ulist_node *cur = NULL;

while (*p) {
parent = *p;
cur = rb_entry(parent, struct ulist_node, rb_node);

if (cur->val < ins->val)
p = &(*p)->rb_right;
else if (cur->val > ins->val)
p = &(*p)->rb_left;
else
return -EEXIST;
}
rb_link_node(&ins->rb_node, parent, p);
rb_insert_color(&ins->rb_node, &ulist->root);
return 0;
}

/**
* ulist_add - add an element to the ulist
* @ulist: ulist to add the element to
Expand Down Expand Up @@ -151,14 +192,13 @@ int ulist_add(struct ulist *ulist, u64 val, u64 aux, gfp_t gfp_mask)
int ulist_add_merge(struct ulist *ulist, u64 val, u64 aux,
u64 *old_aux, gfp_t gfp_mask)
{
int i;

for (i = 0; i < ulist->nnodes; ++i) {
if (ulist->nodes[i].val == val) {
if (old_aux)
*old_aux = ulist->nodes[i].aux;
return 0;
}
int ret = 0;
struct ulist_node *node = NULL;
node = ulist_rbtree_search(ulist, val);
if (node) {
if (old_aux)
*old_aux = node->aux;
return 0;
}

if (ulist->nnodes >= ulist->nodes_alloced) {
Expand Down Expand Up @@ -187,6 +227,8 @@ int ulist_add_merge(struct ulist *ulist, u64 val, u64 aux,
}
ulist->nodes[ulist->nnodes].val = val;
ulist->nodes[ulist->nnodes].aux = aux;
ret = ulist_rbtree_insert(ulist, &ulist->nodes[ulist->nnodes]);
BUG_ON(ret);
++ulist->nnodes;

return 1;
Expand Down
6 changes: 6 additions & 0 deletions trunk/fs/btrfs/ulist.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
#ifndef __ULIST__
#define __ULIST__

#include <linux/list.h>
#include <linux/rbtree.h>

/*
* ulist is a generic data structure to hold a collection of unique u64
* values. The only operations it supports is adding to the list and
Expand All @@ -34,6 +37,7 @@ struct ulist_iterator {
struct ulist_node {
u64 val; /* value to store */
u64 aux; /* auxiliary value saved along with the val */
struct rb_node rb_node; /* used to speed up search */
};

struct ulist {
Expand All @@ -54,6 +58,8 @@ struct ulist {
*/
struct ulist_node *nodes;

struct rb_root root;

/*
* inline storage space for the first ULIST_SIZE entries
*/
Expand Down

0 comments on commit e85a705

Please sign in to comment.