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 cache_head * next;
50 time_t expiry_time;
51 time_t last_refresh;
52
53
54 struct kref ref;
55 unsigned long flags;
56};
57#define CACHE_VALID 0
58#define CACHE_NEGATIVE 1
59#define CACHE_PENDING 2
60
61#define CACHE_NEW_EXPIRY 120
62
63struct cache_detail_procfs {
64 struct proc_dir_entry *proc_ent;
65 struct proc_dir_entry *flush_ent, *channel_ent, *content_ent;
66};
67
68struct cache_detail_pipefs {
69 struct dentry *dir;
70};
71
72struct cache_detail {
73 struct module * owner;
74 int hash_size;
75 struct cache_head ** hash_table;
76 rwlock_t hash_lock;
77
78 atomic_t inuse;
79
80 char *name;
81 void (*cache_put)(struct kref *);
82
83 int (*cache_upcall)(struct cache_detail *,
84 struct cache_head *);
85
86 int (*cache_parse)(struct cache_detail *,
87 char *buf, int len);
88
89 int (*cache_show)(struct seq_file *m,
90 struct cache_detail *cd,
91 struct cache_head *h);
92 void (*warn_no_listener)(struct cache_detail *cd,
93 int has_died);
94
95 struct cache_head * (*alloc)(void);
96 int (*match)(struct cache_head *orig, struct cache_head *new);
97 void (*init)(struct cache_head *orig, struct cache_head *new);
98 void (*update)(struct cache_head *orig, struct cache_head *new);
99
100
101
102
103 time_t flush_time;
104
105 struct list_head others;
106 time_t nextcheck;
107 int entries;
108
109
110 struct list_head queue;
111
112 atomic_t readers;
113 time_t last_close;
114 time_t last_warn;
115
116 union {
117 struct cache_detail_procfs procfs;
118 struct cache_detail_pipefs pipefs;
119 } u;
120 struct net *net;
121};
122
123
124
125
126
127
128struct cache_req {
129 struct cache_deferred_req *(*defer)(struct cache_req *req);
130 int thread_wait;
131
132
133};
134
135
136
137struct cache_deferred_req {
138 struct hlist_node hash;
139 struct list_head recent;
140 struct cache_head *item;
141 void *owner;
142
143 void (*revisit)(struct cache_deferred_req *req,
144 int too_many);
145};
146
147
148extern const struct file_operations cache_file_operations_pipefs;
149extern const struct file_operations content_file_operations_pipefs;
150extern const struct file_operations cache_flush_operations_pipefs;
151
152extern struct cache_head *
153sunrpc_cache_lookup(struct cache_detail *detail,
154 struct cache_head *key, int hash);
155extern struct cache_head *
156sunrpc_cache_update(struct cache_detail *detail,
157 struct cache_head *new, struct cache_head *old, int hash);
158
159extern int
160sunrpc_cache_pipe_upcall(struct cache_detail *detail, struct cache_head *h,
161 void (*cache_request)(struct cache_detail *,
162 struct cache_head *,
163 char **,
164 int *));
165
166
167extern void cache_clean_deferred(void *owner);
168
169static inline struct cache_head *cache_get(struct cache_head *h)
170{
171 kref_get(&h->ref);
172 return h;
173}
174
175
176static inline void cache_put(struct cache_head *h, struct cache_detail *cd)
177{
178 if (atomic_read(&h->ref.refcount) <= 2 &&
179 h->expiry_time < cd->nextcheck)
180 cd->nextcheck = h->expiry_time;
181 kref_put(&h->ref, cd->cache_put);
182}
183
184static inline int cache_valid(struct cache_head *h)
185{
186
187
188
189
190
191
192 return (h->expiry_time != 0 && test_bit(CACHE_VALID, &h->flags));
193}
194
195extern int cache_check(struct cache_detail *detail,
196 struct cache_head *h, struct cache_req *rqstp);
197extern void cache_flush(void);
198extern void cache_purge(struct cache_detail *detail);
199#define NEVER (0x7FFFFFFF)
200extern void __init cache_initialize(void);
201extern int cache_register_net(struct cache_detail *cd, struct net *net);
202extern void cache_unregister_net(struct cache_detail *cd, struct net *net);
203
204extern struct cache_detail *cache_create_net(struct cache_detail *tmpl, struct net *net);
205extern void cache_destroy_net(struct cache_detail *cd, struct net *net);
206
207extern void sunrpc_init_cache_detail(struct cache_detail *cd);
208extern void sunrpc_destroy_cache_detail(struct cache_detail *cd);
209extern int sunrpc_cache_register_pipefs(struct dentry *parent, const char *,
210 umode_t, struct cache_detail *);
211extern void sunrpc_cache_unregister_pipefs(struct cache_detail *);
212
213extern void qword_add(char **bpp, int *lp, char *str);
214extern void qword_addhex(char **bpp, int *lp, char *buf, int blen);
215extern int qword_get(char **bpp, char *dest, int bufsize);
216
217static inline int get_int(char **bpp, int *anint)
218{
219 char buf[50];
220 char *ep;
221 int rv;
222 int len = qword_get(bpp, buf, 50);
223 if (len < 0) return -EINVAL;
224 if (len ==0) return -ENOENT;
225 rv = simple_strtol(buf, &ep, 0);
226 if (*ep) return -EINVAL;
227 *anint = rv;
228 return 0;
229}
230
231
232
233
234
235
236static inline time_t seconds_since_boot(void)
237{
238 struct timespec boot;
239 getboottime(&boot);
240 return get_seconds() - boot.tv_sec;
241}
242
243static inline time_t convert_to_wallclock(time_t sinceboot)
244{
245 struct timespec boot;
246 getboottime(&boot);
247 return boot.tv_sec + sinceboot;
248}
249
250static inline time_t get_expiry(char **bpp)
251{
252 int rv;
253 struct timespec boot;
254
255 if (get_int(bpp, &rv))
256 return 0;
257 if (rv < 0)
258 return 0;
259 getboottime(&boot);
260 return rv - boot.tv_sec;
261}
262
263#endif
264