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};
121
122
123
124
125
126
127struct cache_req {
128 struct cache_deferred_req *(*defer)(struct cache_req *req);
129 int thread_wait;
130
131
132};
133
134
135
136struct cache_deferred_req {
137 struct hlist_node hash;
138 struct list_head recent;
139 struct cache_head *item;
140 void *owner;
141
142 void (*revisit)(struct cache_deferred_req *req,
143 int too_many);
144};
145
146
147extern const struct file_operations cache_file_operations_pipefs;
148extern const struct file_operations content_file_operations_pipefs;
149extern const struct file_operations cache_flush_operations_pipefs;
150
151extern struct cache_head *
152sunrpc_cache_lookup(struct cache_detail *detail,
153 struct cache_head *key, int hash);
154extern struct cache_head *
155sunrpc_cache_update(struct cache_detail *detail,
156 struct cache_head *new, struct cache_head *old, int hash);
157
158extern int
159sunrpc_cache_pipe_upcall(struct cache_detail *detail, struct cache_head *h,
160 void (*cache_request)(struct cache_detail *,
161 struct cache_head *,
162 char **,
163 int *));
164
165
166extern void cache_clean_deferred(void *owner);
167
168static inline struct cache_head *cache_get(struct cache_head *h)
169{
170 kref_get(&h->ref);
171 return h;
172}
173
174
175static inline void cache_put(struct cache_head *h, struct cache_detail *cd)
176{
177 if (atomic_read(&h->ref.refcount) <= 2 &&
178 h->expiry_time < cd->nextcheck)
179 cd->nextcheck = h->expiry_time;
180 kref_put(&h->ref, cd->cache_put);
181}
182
183static inline int cache_valid(struct cache_head *h)
184{
185
186
187
188
189
190
191 return (h->expiry_time != 0 && test_bit(CACHE_VALID, &h->flags));
192}
193
194extern int cache_check(struct cache_detail *detail,
195 struct cache_head *h, struct cache_req *rqstp);
196extern void cache_flush(void);
197extern void cache_purge(struct cache_detail *detail);
198#define NEVER (0x7FFFFFFF)
199extern void __init cache_initialize(void);
200extern int cache_register(struct cache_detail *cd);
201extern int cache_register_net(struct cache_detail *cd, struct net *net);
202extern void cache_unregister(struct cache_detail *cd);
203extern void cache_unregister_net(struct cache_detail *cd, struct net *net);
204
205extern int sunrpc_cache_register_pipefs(struct dentry *parent, const char *,
206 mode_t, struct cache_detail *);
207extern void sunrpc_cache_unregister_pipefs(struct cache_detail *);
208
209extern void qword_add(char **bpp, int *lp, char *str);
210extern void qword_addhex(char **bpp, int *lp, char *buf, int blen);
211extern int qword_get(char **bpp, char *dest, int bufsize);
212
213static inline int get_int(char **bpp, int *anint)
214{
215 char buf[50];
216 char *ep;
217 int rv;
218 int len = qword_get(bpp, buf, 50);
219 if (len < 0) return -EINVAL;
220 if (len ==0) return -ENOENT;
221 rv = simple_strtol(buf, &ep, 0);
222 if (*ep) return -EINVAL;
223 *anint = rv;
224 return 0;
225}
226
227
228
229
230
231
232static inline time_t seconds_since_boot(void)
233{
234 struct timespec boot;
235 getboottime(&boot);
236 return get_seconds() - boot.tv_sec;
237}
238
239static inline time_t convert_to_wallclock(time_t sinceboot)
240{
241 struct timespec boot;
242 getboottime(&boot);
243 return boot.tv_sec + sinceboot;
244}
245
246static inline time_t get_expiry(char **bpp)
247{
248 int rv;
249 struct timespec boot;
250
251 if (get_int(bpp, &rv))
252 return 0;
253 if (rv < 0)
254 return 0;
255 getboottime(&boot);
256 return rv - boot.tv_sec;
257}
258
259#endif
260