1
2
3
4
5
6
7
8
9
10
11
12
13#ifndef _LINUX_SUNRPC_CACHE_H_
14#define _LINUX_SUNRPC_CACHE_H_
15
16#include <linux/kref.h>
17#include <linux/slab.h>
18#include <linux/atomic.h>
19#include <linux/proc_fs.h>
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
48struct cache_head {
49 struct hlist_node cache_list;
50 time64_t expiry_time;
51
52 time64_t last_refresh;
53
54
55
56
57 struct kref ref;
58 unsigned long flags;
59};
60#define CACHE_VALID 0
61#define CACHE_NEGATIVE 1
62#define CACHE_PENDING 2
63#define CACHE_CLEANED 3
64
65#define CACHE_NEW_EXPIRY 120
66
67struct cache_detail {
68 struct module * owner;
69 int hash_size;
70 struct hlist_head * hash_table;
71 spinlock_t hash_lock;
72
73 char *name;
74 void (*cache_put)(struct kref *);
75
76 int (*cache_upcall)(struct cache_detail *,
77 struct cache_head *);
78
79 void (*cache_request)(struct cache_detail *cd,
80 struct cache_head *ch,
81 char **bpp, int *blen);
82
83 int (*cache_parse)(struct cache_detail *,
84 char *buf, int len);
85
86 int (*cache_show)(struct seq_file *m,
87 struct cache_detail *cd,
88 struct cache_head *h);
89 void (*warn_no_listener)(struct cache_detail *cd,
90 int has_died);
91
92 struct cache_head * (*alloc)(void);
93 int (*match)(struct cache_head *orig, struct cache_head *new);
94 void (*init)(struct cache_head *orig, struct cache_head *new);
95 void (*update)(struct cache_head *orig, struct cache_head *new);
96
97
98
99
100 time64_t flush_time;
101
102
103
104
105
106 struct list_head others;
107 time64_t nextcheck;
108 int entries;
109
110
111 struct list_head queue;
112
113 atomic_t writers;
114 time64_t last_close;
115 time64_t last_warn;
116
117 union {
118 struct proc_dir_entry *procfs;
119 struct dentry *pipefs;
120 };
121 struct net *net;
122};
123
124
125
126
127
128
129struct cache_req {
130 struct cache_deferred_req *(*defer)(struct cache_req *req);
131 int thread_wait;
132
133
134};
135
136
137
138struct cache_deferred_req {
139 struct hlist_node hash;
140 struct list_head recent;
141 struct cache_head *item;
142 void *owner;
143
144 void (*revisit)(struct cache_deferred_req *req,
145 int too_many);
146};
147
148
149
150
151
152
153
154
155
156
157static inline time64_t seconds_since_boot(void)
158{
159 struct timespec64 boot;
160 getboottime64(&boot);
161 return ktime_get_real_seconds() - boot.tv_sec;
162}
163
164static inline time64_t convert_to_wallclock(time64_t sinceboot)
165{
166 struct timespec64 boot;
167 getboottime64(&boot);
168 return boot.tv_sec + sinceboot;
169}
170
171extern const struct file_operations cache_file_operations_pipefs;
172extern const struct file_operations content_file_operations_pipefs;
173extern const struct file_operations cache_flush_operations_pipefs;
174
175extern struct cache_head *
176sunrpc_cache_lookup_rcu(struct cache_detail *detail,
177 struct cache_head *key, int hash);
178extern struct cache_head *
179sunrpc_cache_update(struct cache_detail *detail,
180 struct cache_head *new, struct cache_head *old, int hash);
181
182extern int
183sunrpc_cache_pipe_upcall(struct cache_detail *detail, struct cache_head *h);
184extern int
185sunrpc_cache_pipe_upcall_timeout(struct cache_detail *detail,
186 struct cache_head *h);
187
188
189extern void cache_clean_deferred(void *owner);
190
191static inline struct cache_head *cache_get(struct cache_head *h)
192{
193 kref_get(&h->ref);
194 return h;
195}
196
197static inline struct cache_head *cache_get_rcu(struct cache_head *h)
198{
199 if (kref_get_unless_zero(&h->ref))
200 return h;
201 return NULL;
202}
203
204static inline void cache_put(struct cache_head *h, struct cache_detail *cd)
205{
206 if (kref_read(&h->ref) <= 2 &&
207 h->expiry_time < cd->nextcheck)
208 cd->nextcheck = h->expiry_time;
209 kref_put(&h->ref, cd->cache_put);
210}
211
212static inline bool cache_is_expired(struct cache_detail *detail, struct cache_head *h)
213{
214 if (h->expiry_time < seconds_since_boot())
215 return true;
216 if (!test_bit(CACHE_VALID, &h->flags))
217 return false;
218 return detail->flush_time >= h->last_refresh;
219}
220
221extern int cache_check(struct cache_detail *detail,
222 struct cache_head *h, struct cache_req *rqstp);
223extern void cache_flush(void);
224extern void cache_purge(struct cache_detail *detail);
225#define NEVER (0x7FFFFFFF)
226extern void __init cache_initialize(void);
227extern int cache_register_net(struct cache_detail *cd, struct net *net);
228extern void cache_unregister_net(struct cache_detail *cd, struct net *net);
229
230extern struct cache_detail *cache_create_net(const struct cache_detail *tmpl, struct net *net);
231extern void cache_destroy_net(struct cache_detail *cd, struct net *net);
232
233extern void sunrpc_init_cache_detail(struct cache_detail *cd);
234extern void sunrpc_destroy_cache_detail(struct cache_detail *cd);
235extern int sunrpc_cache_register_pipefs(struct dentry *parent, const char *,
236 umode_t, struct cache_detail *);
237extern void sunrpc_cache_unregister_pipefs(struct cache_detail *);
238extern void sunrpc_cache_unhash(struct cache_detail *, struct cache_head *);
239
240
241extern void *cache_seq_start_rcu(struct seq_file *file, loff_t *pos);
242extern void *cache_seq_next_rcu(struct seq_file *file, void *p, loff_t *pos);
243extern void cache_seq_stop_rcu(struct seq_file *file, void *p);
244
245extern void qword_add(char **bpp, int *lp, char *str);
246extern void qword_addhex(char **bpp, int *lp, char *buf, int blen);
247extern int qword_get(char **bpp, char *dest, int bufsize);
248
249static inline int get_int(char **bpp, int *anint)
250{
251 char buf[50];
252 char *ep;
253 int rv;
254 int len = qword_get(bpp, buf, sizeof(buf));
255
256 if (len < 0)
257 return -EINVAL;
258 if (len == 0)
259 return -ENOENT;
260
261 rv = simple_strtol(buf, &ep, 0);
262 if (*ep)
263 return -EINVAL;
264
265 *anint = rv;
266 return 0;
267}
268
269static inline int get_uint(char **bpp, unsigned int *anint)
270{
271 char buf[50];
272 int len = qword_get(bpp, buf, sizeof(buf));
273
274 if (len < 0)
275 return -EINVAL;
276 if (len == 0)
277 return -ENOENT;
278
279 if (kstrtouint(buf, 0, anint))
280 return -EINVAL;
281
282 return 0;
283}
284
285static inline int get_time(char **bpp, time64_t *time)
286{
287 char buf[50];
288 long long ll;
289 int len = qword_get(bpp, buf, sizeof(buf));
290
291 if (len < 0)
292 return -EINVAL;
293 if (len == 0)
294 return -ENOENT;
295
296 if (kstrtoll(buf, 0, &ll))
297 return -EINVAL;
298
299 *time = ll;
300 return 0;
301}
302
303static inline time64_t get_expiry(char **bpp)
304{
305 time64_t rv;
306 struct timespec64 boot;
307
308 if (get_time(bpp, &rv))
309 return 0;
310 if (rv < 0)
311 return 0;
312 getboottime64(&boot);
313 return rv - boot.tv_sec;
314}
315
316#endif
317