Whamcloud - gitweb
add snapfs to cvs
[fs/lustre-release.git] / lustre / snapfs / cache.c
1 /*
2  *
3  *
4  *  Copyright (C) 2000 Stelias Computing, Inc.
5  *  Copyright (C) 2000 Red Hat, Inc.
6  *
7  *
8  */
9
10
11 #include <stdarg.h>
12
13 #include <asm/bitops.h>
14 #include <asm/uaccess.h>
15 #include <asm/system.h>
16
17 #include <linux/errno.h>
18 #include <linux/fs.h>
19 #include <linux/ext2_fs.h>
20 #include <linux/malloc.h>
21 #include <linux/vmalloc.h>
22 #include <linux/sched.h>
23 #include <linux/stat.h>
24 #include <linux/string.h>
25 #include <linux/locks.h>
26 #include <linux/blkdev.h>
27 #include <linux/init.h>
28 #define __NO_VERSION__
29 #include <linux/module.h>
30
31 #include <linux/filter.h>
32 #include <linux/snapfs.h>
33 #include <linux/snapsupport.h>
34
35 /*
36  * XXX - Not sure for snapfs that the cache functions are even needed.
37  * Can't all lookups be done by an inode->superblock->u.generic_sbp
38  * lookup?
39  */
40
41 /*
42    This file contains the routines associated with managing a
43    cache of files .  These caches need to be found
44    fast so they are hashed by the device, with an attempt to have
45    collision chains of length 1.
46 */
47
48 /* the intent of this hash is to have collision chains of length 1 */
49 #define CACHES_BITS 8
50 #define CACHES_SIZE (1 << CACHES_BITS)
51 #define CACHES_MASK CACHES_SIZE - 1
52 static struct list_head snap_caches[CACHES_SIZE];
53
54 static inline int snap_cache_hash(kdev_t dev)
55 {
56         return (CACHES_MASK) & ((0x000F & (dev)) + ((0x0F00 & (dev)) >>8));
57 }
58
59 inline void snap_cache_add(struct snap_cache *cache, kdev_t dev)
60 {
61         list_add(&cache->cache_chain,
62                  &snap_caches[snap_cache_hash(dev)]);
63         cache->cache_dev = dev;
64 }
65
66 inline void snap_init_cache_hash(void)
67 {
68         int i;
69         for ( i = 0; i < CACHES_SIZE; i++ ) {
70                 INIT_LIST_HEAD(&snap_caches[i]);
71         }
72 }
73
74 /* map a device to a cache */
75 struct snap_cache *snap_find_cache(kdev_t dev)
76 {
77         struct snap_cache *cache;
78         struct list_head *lh, *tmp;
79
80         lh = tmp = &(snap_caches[snap_cache_hash(dev)]);
81         while ( (tmp = lh->next) != lh ) {
82                 cache = list_entry(tmp, struct snap_cache, cache_chain);
83                 if ( cache->cache_dev == dev )
84                         return cache;
85         }
86         return NULL;
87 }
88
89
90 /* map an inode to a cache */
91 struct snap_cache *snap_get_cache(struct inode *inode)
92 {
93         struct snap_cache *cache;
94
95         /* find the correct snap_cache here, based on the device */
96         cache = snap_find_cache(inode->i_dev);
97         if ( !cache ) {
98                 printk("WARNING: no  cache for dev %d, ino %ld\n",
99                        inode->i_dev, inode->i_ino);
100                 return NULL;
101         }
102
103         return cache;
104 }
105
106
107 /* another debugging routine: check fs is InterMezzo fs */
108 int snap_ispresto(struct inode *inode)
109 {
110         struct snap_cache *cache;
111
112         if ( !inode )
113                 return 0;
114         cache = snap_get_cache(inode);
115         if ( !cache )
116                 return 0;
117         return (inode->i_dev == cache->cache_dev);
118 }
119
120 /* setup a cache structure when we need one */
121 struct snap_cache *snap_init_cache(void)
122 {
123         struct snap_cache *cache;
124
125         /* make a snap_cache structure for the hash */
126         SNAP_ALLOC(cache, struct snap_cache *, sizeof(struct snap_cache));
127         if ( cache ) {
128                 memset(cache, 0, sizeof(struct snap_cache));
129                 INIT_LIST_HEAD(&cache->cache_chain);
130                 INIT_LIST_HEAD(&cache->cache_clone_list);
131         }
132         return cache;
133 }
134
135
136 /* free a cache structure and all of the memory it is pointing to */
137 inline void snap_free_cache(struct snap_cache *cache)
138 {
139         if (!cache)
140                 return;
141
142
143         SNAP_FREE(cache, sizeof(struct snap_cache));
144 }
145