cache.h
上传用户:szlgq88
上传日期:2009-04-28
资源大小:48287k
文件大小:10k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * include/linux/sunrpc/cache.h
  3.  *
  4.  * Generic code for various authentication-related caches
  5.  * used by sunrpc clients and servers.
  6.  *
  7.  * Copyright (C) 2002 Neil Brown <neilb@cse.unsw.edu.au>
  8.  *
  9.  * Released under terms in GPL version 2.  See COPYING.
  10.  *
  11.  */
  12. #ifndef _LINUX_SUNRPC_CACHE_H_
  13. #define _LINUX_SUNRPC_CACHE_H_
  14. #include <linux/slab.h>
  15. #include <asm/atomic.h>
  16. #include <linux/proc_fs.h>
  17. /*
  18.  * Each cache requires:
  19.  *  - A 'struct cache_detail' which contains information specific to the cache
  20.  *    for common code to use.
  21.  *  - An item structure that must contain a "struct cache_head"
  22.  *  - A lookup function defined using DefineCacheLookup
  23.  *  - A 'put' function that can release a cache item. It will only
  24.  *    be called after cache_put has succeed, so there are guarantee
  25.  *    to be no references.
  26.  *  - A function to calculate a hash of an item's key.
  27.  *
  28.  * as well as assorted code fragments (e.g. compare keys) and numbers
  29.  * (e.g. hash size, goal_age, etc).
  30.  *
  31.  * Each cache must be registered so that it can be cleaned regularly.
  32.  * When the cache is unregistered, it is flushed completely.
  33.  *
  34.  * Entries have a ref count and a 'hashed' flag which counts the existance
  35.  * in the hash table.
  36.  * We only expire entries when refcount is zero.
  37.  * Existance in the cache is counted  the refcount.
  38.  */
  39. /* Every cache item has a common header that is used
  40.  * for expiring and refreshing entries.
  41.  * 
  42.  */
  43. struct cache_head {
  44. struct cache_head * next;
  45. time_t expiry_time; /* After time time, don't use the data */
  46. time_t last_refresh;   /* If CACHE_PENDING, this is when upcall 
  47.  * was sent, else this is when update was received
  48.  */
  49. atomic_t  refcnt;
  50. unsigned long flags;
  51. };
  52. #define CACHE_VALID 0 /* Entry contains valid data */
  53. #define CACHE_NEGATIVE 1 /* Negative entry - there is no match for the key */
  54. #define CACHE_PENDING 2 /* An upcall has been sent but no reply received yet*/
  55. #define CACHE_NEW_EXPIRY 120 /* keep new things pending confirmation for 120 seconds */
  56. struct cache_detail {
  57. struct module * owner;
  58. int hash_size;
  59. struct cache_head ** hash_table;
  60. rwlock_t hash_lock;
  61. atomic_t inuse; /* active user-space update or lookup */
  62. char *name;
  63. void (*cache_put)(struct cache_head *,
  64.      struct cache_detail*);
  65. void (*cache_request)(struct cache_detail *cd,
  66.  struct cache_head *h,
  67.  char **bpp, int *blen);
  68. int (*cache_parse)(struct cache_detail *,
  69.        char *buf, int len);
  70. int (*cache_show)(struct seq_file *m,
  71.       struct cache_detail *cd,
  72.       struct cache_head *h);
  73. /* fields below this comment are for internal use
  74.  * and should not be touched by cache owners
  75.  */
  76. time_t flush_time; /* flush all cache items with last_refresh
  77.  * earlier than this */
  78. struct list_head others;
  79. time_t nextcheck;
  80. int entries;
  81. /* fields for communication over channel */
  82. struct list_head queue;
  83. struct proc_dir_entry *proc_ent;
  84. struct proc_dir_entry   *flush_ent, *channel_ent, *content_ent;
  85. atomic_t readers; /* how many time is /chennel open */
  86. time_t last_close; /* if no readers, when did last close */
  87. time_t last_warn; /* when we last warned about no readers */
  88. void (*warn_no_listener)(struct cache_detail *cd);
  89. };
  90. /* this must be embedded in any request structure that
  91.  * identifies an object that will want a callback on
  92.  * a cache fill
  93.  */
  94. struct cache_req {
  95. struct cache_deferred_req *(*defer)(struct cache_req *req);
  96. };
  97. /* this must be embedded in a deferred_request that is being
  98.  * delayed awaiting cache-fill
  99.  */
  100. struct cache_deferred_req {
  101. struct list_head hash; /* on hash chain */
  102. struct list_head recent; /* on fifo */
  103. struct cache_head *item;  /* cache item we wait on */
  104. time_t recv_time;
  105. void *owner; /* we might need to discard all defered requests
  106.  * owned by someone */
  107. void (*revisit)(struct cache_deferred_req *req,
  108.    int too_many);
  109. };
  110. /*
  111.  * just like a template in C++, this macro does cache lookup
  112.  * for us.
  113.  * The function is passed some sort of HANDLE from which a cache_detail
  114.  * structure can be determined (via SETUP, DETAIL), a template
  115.  * cache entry (type RTN*), and a "set" flag.  Using the HASHFN and the 
  116.  * TEST, the function will try to find a matching cache entry in the cache.
  117.  * If "set" == 0 :
  118.  *    If an entry is found, it is returned
  119.  *    If no entry is found, a new non-VALID entry is created.
  120.  * If "set" == 1 and INPLACE == 0 :
  121.  *    If no entry is found a new one is inserted with data from "template"
  122.  *    If a non-CACHE_VALID entry is found, it is updated from template using UPDATE
  123.  *    If a CACHE_VALID entry is found, a new entry is swapped in with data
  124.  *       from "template"
  125.  * If set == 1, and INPLACE == 1 :
  126.  *    As above, except that if a CACHE_VALID entry is found, we UPDATE in place
  127.  *       instead of swapping in a new entry.
  128.  *
  129.  * If the passed handle has the CACHE_NEGATIVE flag set, then UPDATE is not
  130.  * run but insteead CACHE_NEGATIVE is set in any new item.
  131.  *  In any case, the new entry is returned with a reference count.
  132.  *
  133.  *    
  134.  * RTN is a struct type for a cache entry
  135.  * MEMBER is the member of the cache which is cache_head, which must be first
  136.  * FNAME is the name for the function
  137.  * ARGS are arguments to function and must contain RTN *item, int set.  May
  138.  *   also contain something to be usedby SETUP or DETAIL to find cache_detail.
  139.  * SETUP  locates the cache detail and makes it available as...
  140.  * DETAIL identifies the cache detail, possibly set up by SETUP
  141.  * HASHFN returns a hash value of the cache entry "item"
  142.  * TEST  tests if "tmp" matches "item"
  143.  * INIT copies key information from "item" to "new"
  144.  * UPDATE copies content information from "item" to "tmp"
  145.  * INPLACE is true if updates can happen inplace rather than allocating a new structure
  146.  *
  147.  * WARNING: any substantial changes to this must be reflected in
  148.  *   net/sunrpc/svcauth.c(auth_domain_lookup)
  149.  *  which is a similar routine that is open-coded.
  150.  */
  151. #define DefineCacheLookup(RTN,MEMBER,FNAME,ARGS,SETUP,DETAIL,HASHFN,TEST,INIT,UPDATE,INPLACE)
  152. RTN *FNAME ARGS
  153. {
  154. RTN *tmp, *new=NULL;
  155. struct cache_head **hp, **head;
  156. SETUP;
  157. head = &(DETAIL)->hash_table[HASHFN];
  158.  retry:
  159. if (set||new) write_lock(&(DETAIL)->hash_lock);
  160. else read_lock(&(DETAIL)->hash_lock);
  161. for(hp=head; *hp != NULL; hp = &tmp->MEMBER.next) {
  162. tmp = container_of(*hp, RTN, MEMBER);
  163. if (TEST) { /* found a match */
  164. if (set && !INPLACE && test_bit(CACHE_VALID, &tmp->MEMBER.flags) && !new) 
  165. break;
  166. if (new)
  167. {INIT;}
  168. if (set) {
  169. if (!INPLACE && test_bit(CACHE_VALID, &tmp->MEMBER.flags))
  170. { /* need to swap in new */
  171. RTN *t2;
  172. new->MEMBER.next = tmp->MEMBER.next;
  173. *hp = &new->MEMBER;
  174. tmp->MEMBER.next = NULL;
  175. t2 = tmp; tmp = new; new = t2;
  176. }
  177. if (test_bit(CACHE_NEGATIVE,  &item->MEMBER.flags))
  178. set_bit(CACHE_NEGATIVE, &tmp->MEMBER.flags);
  179. else {
  180. UPDATE;
  181. clear_bit(CACHE_NEGATIVE, &tmp->MEMBER.flags);
  182. }
  183. }
  184. cache_get(&tmp->MEMBER);
  185. if (set||new) write_unlock(&(DETAIL)->hash_lock);
  186. else read_unlock(&(DETAIL)->hash_lock);
  187. if (set)
  188. cache_fresh(DETAIL, &tmp->MEMBER, item->MEMBER.expiry_time); 
  189. if (set && !INPLACE && new) cache_fresh(DETAIL, &new->MEMBER, 0);
  190. if (new) (DETAIL)->cache_put(&new->MEMBER, DETAIL);
  191. return tmp;
  192. }
  193. }
  194. /* Didn't find anything */
  195. if (new) {
  196. INIT;
  197. new->MEMBER.next = *head;
  198. *head = &new->MEMBER;
  199. (DETAIL)->entries ++;
  200. cache_get(&new->MEMBER);
  201. if (set) {
  202. tmp = new;
  203. if (test_bit(CACHE_NEGATIVE, &item->MEMBER.flags))
  204. set_bit(CACHE_NEGATIVE, &tmp->MEMBER.flags);
  205. else {UPDATE;}
  206. }
  207. }
  208. if (set||new) write_unlock(&(DETAIL)->hash_lock);
  209. else read_unlock(&(DETAIL)->hash_lock);
  210. if (new && set)
  211. cache_fresh(DETAIL, &new->MEMBER, item->MEMBER.expiry_time);
  212. if (new)        
  213. return new;
  214. new = kmalloc(sizeof(*new), GFP_KERNEL);
  215. if (new) {
  216. cache_init(&new->MEMBER);
  217. goto retry;
  218. }
  219. return NULL;
  220. }
  221. #define DefineSimpleCacheLookup(STRUCT,INPLACE)
  222. DefineCacheLookup(struct STRUCT, h, STRUCT##_lookup, (struct STRUCT *item, int set), /*no setup */,
  223.   & STRUCT##_cache, STRUCT##_hash(item), STRUCT##_match(item, tmp),
  224.   STRUCT##_init(new, item), STRUCT##_update(tmp, item),INPLACE)
  225. #define cache_for_each(pos, detail, index, member) 
  226. for (({read_lock(&(detail)->hash_lock); index = (detail)->hash_size;}) ;
  227.      ({if (index==0)read_unlock(&(detail)->hash_lock); index--;});
  228. )
  229. for (pos = container_of((detail)->hash_table[index], typeof(*pos), member);
  230.      &pos->member;
  231.      pos = container_of(pos->member.next, typeof(*pos), member))
  232.      
  233. extern void cache_clean_deferred(void *owner);
  234. static inline struct cache_head  *cache_get(struct cache_head *h)
  235. {
  236. atomic_inc(&h->refcnt);
  237. return h;
  238. }
  239. static inline int cache_put(struct cache_head *h, struct cache_detail *cd)
  240. {
  241. if (atomic_read(&h->refcnt) <= 2 &&
  242.     h->expiry_time < cd->nextcheck)
  243. cd->nextcheck = h->expiry_time;
  244. return atomic_dec_and_test(&h->refcnt);
  245. }
  246. extern void cache_init(struct cache_head *h);
  247. extern void cache_fresh(struct cache_detail *detail,
  248. struct cache_head *head, time_t expiry);
  249. extern int cache_check(struct cache_detail *detail,
  250.        struct cache_head *h, struct cache_req *rqstp);
  251. extern void cache_flush(void);
  252. extern void cache_purge(struct cache_detail *detail);
  253. #define NEVER (0x7FFFFFFF)
  254. extern void cache_register(struct cache_detail *cd);
  255. extern int cache_unregister(struct cache_detail *cd);
  256. extern void qword_add(char **bpp, int *lp, char *str);
  257. extern void qword_addhex(char **bpp, int *lp, char *buf, int blen);
  258. extern int qword_get(char **bpp, char *dest, int bufsize);
  259. static inline int get_int(char **bpp, int *anint)
  260. {
  261. char buf[50];
  262. char *ep;
  263. int rv;
  264. int len = qword_get(bpp, buf, 50);
  265. if (len < 0) return -EINVAL;
  266. if (len ==0) return -ENOENT;
  267. rv = simple_strtol(buf, &ep, 0);
  268. if (*ep) return -EINVAL;
  269. *anint = rv;
  270. return 0;
  271. }
  272. static inline time_t get_expiry(char **bpp)
  273. {
  274. int rv;
  275. if (get_int(bpp, &rv))
  276. return 0;
  277. if (rv < 0)
  278. return 0;
  279. return rv;
  280. }
  281. #endif /*  _LINUX_SUNRPC_CACHE_H_ */