cache.h 6.9 KB
Newer Older
L
Linus Torvalds 已提交
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
/*
 * include/linux/sunrpc/cache.h
 *
 * Generic code for various authentication-related caches
 * used by sunrpc clients and servers.
 *
 * Copyright (C) 2002 Neil Brown <neilb@cse.unsw.edu.au>
 *
 * Released under terms in GPL version 2.  See COPYING.
 *
 */

#ifndef _LINUX_SUNRPC_CACHE_H_
#define _LINUX_SUNRPC_CACHE_H_

#include <linux/slab.h>
#include <asm/atomic.h>
#include <linux/proc_fs.h>

/*
 * Each cache requires:
 *  - A 'struct cache_detail' which contains information specific to the cache
 *    for common code to use.
 *  - An item structure that must contain a "struct cache_head"
 *  - A lookup function defined using DefineCacheLookup
 *  - A 'put' function that can release a cache item. It will only
 *    be called after cache_put has succeed, so there are guarantee
 *    to be no references.
 *  - A function to calculate a hash of an item's key.
 *
 * as well as assorted code fragments (e.g. compare keys) and numbers
 * (e.g. hash size, goal_age, etc).
 *
 * Each cache must be registered so that it can be cleaned regularly.
 * When the cache is unregistered, it is flushed completely.
 *
 * Entries have a ref count and a 'hashed' flag which counts the existance
 * in the hash table.
 * We only expire entries when refcount is zero.
 * Existance in the cache is counted  the refcount.
 */

/* Every cache item has a common header that is used
 * for expiring and refreshing entries.
 * 
 */
struct cache_head {
	struct cache_head * next;
	time_t		expiry_time;	/* After time time, don't use the data */
	time_t		last_refresh;   /* If CACHE_PENDING, this is when upcall 
					 * was sent, else this is when update was received
					 */
53
	struct kref	ref;
L
Linus Torvalds 已提交
54 55 56 57 58 59 60 61
	unsigned long	flags;
};
#define	CACHE_VALID	0	/* Entry contains valid data */
#define	CACHE_NEGATIVE	1	/* Negative entry - there is no match for the key */
#define	CACHE_PENDING	2	/* An upcall has been sent but no reply received yet*/

#define	CACHE_NEW_EXPIRY 120	/* keep new things pending confirmation for 120 seconds */

62 63 64 65 66
struct cache_detail_procfs {
	struct proc_dir_entry	*proc_ent;
	struct proc_dir_entry   *flush_ent, *channel_ent, *content_ent;
};

67 68 69 70
struct cache_detail_pipefs {
	struct dentry *dir;
};

L
Linus Torvalds 已提交
71
struct cache_detail {
72
	struct module *		owner;
L
Linus Torvalds 已提交
73 74 75 76 77 78 79
	int			hash_size;
	struct cache_head **	hash_table;
	rwlock_t		hash_lock;

	atomic_t		inuse; /* active user-space update or lookup */

	char			*name;
80
	void			(*cache_put)(struct kref *);
L
Linus Torvalds 已提交
81

82 83 84
	int			(*cache_upcall)(struct cache_detail *,
						struct cache_head *);

L
Linus Torvalds 已提交
85 86 87 88 89 90
	int			(*cache_parse)(struct cache_detail *,
					       char *buf, int len);

	int			(*cache_show)(struct seq_file *m,
					      struct cache_detail *cd,
					      struct cache_head *h);
91 92
	void			(*warn_no_listener)(struct cache_detail *cd,
					      int has_died);
L
Linus Torvalds 已提交
93

94 95 96 97 98
	struct cache_head *	(*alloc)(void);
	int			(*match)(struct cache_head *orig, struct cache_head *new);
	void			(*init)(struct cache_head *orig, struct cache_head *new);
	void			(*update)(struct cache_head *orig, struct cache_head *new);

L
Linus Torvalds 已提交
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
	/* fields below this comment are for internal use
	 * and should not be touched by cache owners
	 */
	time_t			flush_time;		/* flush all cache items with last_refresh
							 * earlier than this */
	struct list_head	others;
	time_t			nextcheck;
	int			entries;

	/* fields for communication over channel */
	struct list_head	queue;

	atomic_t		readers;		/* how many time is /chennel open */
	time_t			last_close;		/* if no readers, when did last close */
	time_t			last_warn;		/* when we last warned about no readers */
114 115 116

	union {
		struct cache_detail_procfs procfs;
117
		struct cache_detail_pipefs pipefs;
118
	} u;
L
Linus Torvalds 已提交
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
};


/* this must be embedded in any request structure that
 * identifies an object that will want a callback on
 * a cache fill
 */
struct cache_req {
	struct cache_deferred_req *(*defer)(struct cache_req *req);
};
/* this must be embedded in a deferred_request that is being
 * delayed awaiting cache-fill
 */
struct cache_deferred_req {
	struct list_head	hash;	/* on hash chain */
	struct list_head	recent; /* on fifo */
	struct cache_head	*item;  /* cache item we wait on */
	void			*owner; /* we might need to discard all defered requests
					 * owned by someone */
	void			(*revisit)(struct cache_deferred_req *req,
					   int too_many);
};

142

143 144 145 146
extern const struct file_operations cache_file_operations_pipefs;
extern const struct file_operations content_file_operations_pipefs;
extern const struct file_operations cache_flush_operations_pipefs;

147 148 149 150 151 152 153
extern struct cache_head *
sunrpc_cache_lookup(struct cache_detail *detail,
		    struct cache_head *key, int hash);
extern struct cache_head *
sunrpc_cache_update(struct cache_detail *detail,
		    struct cache_head *new, struct cache_head *old, int hash);

154 155 156 157 158 159 160
extern int
sunrpc_cache_pipe_upcall(struct cache_detail *detail, struct cache_head *h,
		void (*cache_request)(struct cache_detail *,
				      struct cache_head *,
				      char **,
				      int *));

L
Linus Torvalds 已提交
161 162 163 164 165

extern void cache_clean_deferred(void *owner);

static inline struct cache_head  *cache_get(struct cache_head *h)
{
166
	kref_get(&h->ref);
L
Linus Torvalds 已提交
167 168 169 170
	return h;
}


171
static inline void cache_put(struct cache_head *h, struct cache_detail *cd)
L
Linus Torvalds 已提交
172
{
173
	if (atomic_read(&h->ref.refcount) <= 2 &&
L
Linus Torvalds 已提交
174 175
	    h->expiry_time < cd->nextcheck)
		cd->nextcheck = h->expiry_time;
176
	kref_put(&h->ref, cd->cache_put);
L
Linus Torvalds 已提交
177 178
}

179 180 181 182 183 184 185 186 187 188 189
static inline int cache_valid(struct cache_head *h)
{
	/* If an item has been unhashed pending removal when
	 * the refcount drops to 0, the expiry_time will be
	 * set to 0.  We don't want to consider such items
	 * valid in this context even though CACHE_VALID is
	 * set.
	 */
	return (h->expiry_time != 0 && test_bit(CACHE_VALID, &h->flags));
}

L
Linus Torvalds 已提交
190 191 192 193 194
extern int cache_check(struct cache_detail *detail,
		       struct cache_head *h, struct cache_req *rqstp);
extern void cache_flush(void);
extern void cache_purge(struct cache_detail *detail);
#define NEVER (0x7FFFFFFF)
195
extern void __init cache_initialize(void);
196
extern int cache_register(struct cache_detail *cd);
197
extern void cache_unregister(struct cache_detail *cd);
L
Linus Torvalds 已提交
198

199 200 201 202
extern int sunrpc_cache_register_pipefs(struct dentry *parent, const char *,
					mode_t, struct cache_detail *);
extern void sunrpc_cache_unregister_pipefs(struct cache_detail *);

L
Linus Torvalds 已提交
203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230
extern void qword_add(char **bpp, int *lp, char *str);
extern void qword_addhex(char **bpp, int *lp, char *buf, int blen);
extern int qword_get(char **bpp, char *dest, int bufsize);

static inline int get_int(char **bpp, int *anint)
{
	char buf[50];
	char *ep;
	int rv;
	int len = qword_get(bpp, buf, 50);
	if (len < 0) return -EINVAL;
	if (len ==0) return -ENOENT;
	rv = simple_strtol(buf, &ep, 0);
	if (*ep) return -EINVAL;
	*anint = rv;
	return 0;
}

static inline time_t get_expiry(char **bpp)
{
	int rv;
	if (get_int(bpp, &rv))
		return 0;
	if (rv < 0)
		return 0;
	return rv;
}

231 232 233 234 235 236
static inline void sunrpc_invalidate(struct cache_head *h,
				     struct cache_detail *detail)
{
	h->expiry_time = get_seconds() - 1;
	detail->nextcheck = get_seconds();
}
L
Linus Torvalds 已提交
237
#endif /*  _LINUX_SUNRPC_CACHE_H_ */