1 #include <linux/slab.h>
3 #include <linux/string.h>
4 #include <linux/spinlock.h>
5 #include <linux/ceph/string_table.h>
7 static DEFINE_SPINLOCK(string_tree_lock
);
8 static struct rb_root string_tree
= RB_ROOT
;
10 struct ceph_string
*ceph_find_or_create_string(const char* str
, size_t len
)
12 struct ceph_string
*cs
, *exist
;
13 struct rb_node
**p
, *parent
;
17 spin_lock(&string_tree_lock
);
18 p
= &string_tree
.rb_node
;
20 exist
= rb_entry(*p
, struct ceph_string
, node
);
21 ret
= ceph_compare_string(exist
, str
, len
);
30 if (exist
&& !kref_get_unless_zero(&exist
->kref
)) {
31 rb_erase(&exist
->node
, &string_tree
);
32 RB_CLEAR_NODE(&exist
->node
);
35 spin_unlock(&string_tree_lock
);
39 cs
= kmalloc(sizeof(*cs
) + len
+ 1, GFP_NOFS
);
45 memcpy(cs
->str
, str
, len
);
51 p
= &string_tree
.rb_node
;
52 spin_lock(&string_tree_lock
);
55 exist
= rb_entry(*p
, struct ceph_string
, node
);
56 ret
= ceph_compare_string(exist
, str
, len
);
67 rb_link_node(&cs
->node
, parent
, p
);
68 rb_insert_color(&cs
->node
, &string_tree
);
69 } else if (!kref_get_unless_zero(&exist
->kref
)) {
70 rb_erase(&exist
->node
, &string_tree
);
71 RB_CLEAR_NODE(&exist
->node
);
74 spin_unlock(&string_tree_lock
);
85 EXPORT_SYMBOL(ceph_find_or_create_string
);
87 void ceph_release_string(struct kref
*ref
)
89 struct ceph_string
*cs
= container_of(ref
, struct ceph_string
, kref
);
91 spin_lock(&string_tree_lock
);
92 if (!RB_EMPTY_NODE(&cs
->node
)) {
93 rb_erase(&cs
->node
, &string_tree
);
94 RB_CLEAR_NODE(&cs
->node
);
96 spin_unlock(&string_tree_lock
);
100 EXPORT_SYMBOL(ceph_release_string
);
102 bool ceph_strings_empty(void)
104 return RB_EMPTY_ROOT(&string_tree
);