-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathnamecache.c
More file actions
127 lines (109 loc) · 2.42 KB
/
namecache.c
File metadata and controls
127 lines (109 loc) · 2.42 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#include <linux/types.h>
#include <linux/socket.h>
#include <net/sock.h>
#include <linux/jhash.h>
#include <linux/list.h>
#include <linux/inname.h>
#include "namestack_priv.h"
struct name_sock_list
{
struct list_head entry;
struct socket *sock;
};
static u32 name_cache_shift;
#define name_cache_size (1 << name_cache_shift)
static struct name_sock_list *name_cache;
static DEFINE_SPINLOCK(name_cache_lock);
static inline void lock_name_cache(void)
{
spin_lock(&name_cache_lock);
}
static inline void unlock_name_cache(void)
{
spin_unlock(&name_cache_lock);
}
int name_cache_init(void)
{
int err;
name_cache_shift = 4;
name_cache = kmalloc(name_cache_size * sizeof(struct name_sock_list),
GFP_ATOMIC);
if (name_cache) {
int i;
for (i = 0; i < name_cache_size; i++) {
INIT_LIST_HEAD(&name_cache[i].entry);
name_cache[i].sock = NULL;
}
err = 0;
}
else {
/* defensive line to protect against a broken caller */
name_cache_shift = 0;
err = -ENOMEM;
}
return err;
}
static inline u32 name_hash(const char *name)
{
return jhash(name, strlen(name), 0) & (name_cache_size - 1);
}
static struct name_sock_list *__name_cache_find(const char *name, u32 bucket)
{
struct name_sock_list *ptr;
list_for_each_entry(ptr, &name_cache[bucket].entry, entry) {
struct sock *sk = ptr->sock->sk;
struct name_stream_sock *name_sk = name_stream_sk(sk);
if (!strcmp(name_sk->sname.sname_addr.name, name))
return ptr;
}
return NULL;
}
int name_cache_add(const char *name, struct socket *sock)
{
int err;
u32 bucket = name_hash(name);
struct name_sock_list *ptr;
lock_name_cache();
ptr = __name_cache_find(name, bucket);
if (ptr) {
err = -EALREADY;
goto out;
}
ptr = kmalloc(sizeof(struct name_sock_list), GFP_ATOMIC);
if (!ptr) {
err = -ENOMEM;
goto out;
}
ptr->sock = sock;
INIT_LIST_HEAD(&ptr->entry);
list_add_tail(&name_cache[bucket].entry, &ptr->entry);
err = 0;
out:
unlock_name_cache();
return err;
}
void name_cache_delete(const char *name)
{
u32 bucket = name_hash(name);
struct name_sock_list *ptr;
lock_name_cache();
ptr = __name_cache_find(name, bucket);
if (ptr) {
list_del(&ptr->entry);
kfree(ptr);
}
unlock_name_cache();
}
void name_cache_free(void)
{
int i;
for (i = 0; i < name_cache_size; i++) {
struct name_sock_list *itr, *next;
list_for_each_entry_safe(itr, next, &name_cache[i].entry,
entry) {
list_del(&itr->entry);
kfree(itr);
}
}
kfree(name_cache);
}