~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/net/ceph/string_table.c

Version: ~ [ linux-5.1-rc2 ] ~ [ linux-5.0.4 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.31 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.108 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.165 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.177 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.137 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.63 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.39.4 ] ~ [ linux-2.6.38.8 ] ~ [ linux-2.6.37.6 ] ~ [ linux-2.6.36.4 ] ~ [ linux-2.6.35.14 ] ~ [ linux-2.6.34.15 ] ~ [ linux-2.6.33.20 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp