^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #include <linux/gfp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/ceph/string_table.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) static DEFINE_SPINLOCK(string_tree_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) static struct rb_root string_tree = RB_ROOT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) struct ceph_string *ceph_find_or_create_string(const char* str, size_t len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) struct ceph_string *cs, *exist;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) struct rb_node **p, *parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) exist = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) spin_lock(&string_tree_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) p = &string_tree.rb_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) while (*p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) exist = rb_entry(*p, struct ceph_string, node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) ret = ceph_compare_string(exist, str, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) if (ret > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) p = &(*p)->rb_left;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) else if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) p = &(*p)->rb_right;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) exist = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) if (exist && !kref_get_unless_zero(&exist->kref)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) rb_erase(&exist->node, &string_tree);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) RB_CLEAR_NODE(&exist->node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) exist = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) spin_unlock(&string_tree_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) if (exist)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) return exist;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) cs = kmalloc(sizeof(*cs) + len + 1, GFP_NOFS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) if (!cs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) kref_init(&cs->kref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) cs->len = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) memcpy(cs->str, str, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) cs->str[len] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) retry:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) exist = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) parent = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) p = &string_tree.rb_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) spin_lock(&string_tree_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) while (*p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) parent = *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) exist = rb_entry(*p, struct ceph_string, node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) ret = ceph_compare_string(exist, str, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) if (ret > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) p = &(*p)->rb_left;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) else if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) p = &(*p)->rb_right;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) exist = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) if (!exist) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) rb_link_node(&cs->node, parent, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) rb_insert_color(&cs->node, &string_tree);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) } else if (!kref_get_unless_zero(&exist->kref)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) rb_erase(&exist->node, &string_tree);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) RB_CLEAR_NODE(&exist->node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) ret = -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) spin_unlock(&string_tree_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) if (ret == -EAGAIN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) goto retry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) if (exist) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) kfree(cs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) cs = exist;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) return cs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) EXPORT_SYMBOL(ceph_find_or_create_string);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) void ceph_release_string(struct kref *ref)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) struct ceph_string *cs = container_of(ref, struct ceph_string, kref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) spin_lock(&string_tree_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) if (!RB_EMPTY_NODE(&cs->node)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) rb_erase(&cs->node, &string_tree);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) RB_CLEAR_NODE(&cs->node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) spin_unlock(&string_tree_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) kfree_rcu(cs, rcu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) EXPORT_SYMBOL(ceph_release_string);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) bool ceph_strings_empty(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) return RB_EMPTY_ROOT(&string_tree);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) }