Import 2.3.10pre5
[davej-history.git] / fs / coda / cache.c
blobd3412e52c4558ac0ed8a50077ae96f42af72fd2b
1 /*
2 * Cache operations for Coda.
3 * For Linux 2.1: (C) 1997 Carnegie Mellon University
5 * Carnegie Mellon encourages users of this code to contribute improvements
6 * to the Coda project. Contact Peter Braam <coda@cs.cmu.edu>.
7 */
9 #include <linux/types.h>
10 #include <linux/kernel.h>
11 #include <linux/sched.h>
12 #include <linux/fs.h>
13 #include <linux/stat.h>
14 #include <linux/errno.h>
15 #include <linux/locks.h>
16 #include <asm/segment.h>
17 #include <asm/uaccess.h>
18 #include <linux/string.h>
19 #include <linux/list.h>
21 #include <linux/coda.h>
22 #include <linux/coda_linux.h>
23 #include <linux/coda_psdev.h>
24 #include <linux/coda_fs_i.h>
25 #include <linux/coda_cache.h>
27 static void coda_ccinsert(struct coda_cache *el, struct super_block *sb);
28 static void coda_cninsert(struct coda_cache *el, struct coda_inode_info *cii);
29 static void coda_ccremove(struct coda_cache *el);
30 static void coda_cnremove(struct coda_cache *el);
31 static void coda_cache_create(struct inode *inode, int mask);
32 static struct coda_cache * coda_cache_find(struct inode *inode);
35 /* insert a acl-cache entry in sb list */
36 static void coda_ccinsert(struct coda_cache *el, struct super_block *sb)
38 struct coda_sb_info *sbi = coda_sbp(sb);
39 ENTRY;
40 /* third test verifies cc was initialized before adding it
41 to the sblist. Probably superfluous */
42 if ( !sbi || !el || !list_empty(&el->cc_cclist) ) {
43 printk("coda_ccinsert: NULL sbi or el->cc_cclist not empty!\n");
44 return ;
47 list_add(&el->cc_cclist, &sbi->sbi_cchead);
50 /* insert a acl-cache entry in the inode list */
51 static void coda_cninsert(struct coda_cache *el, struct coda_inode_info *cii)
53 ENTRY;
54 if ( !cii || !el || ! list_empty(&el->cc_cnlist)) {
55 printk("coda_cninsert: NULL cii or el->cc_cnlist not empty!\n");
56 return ;
58 list_add(&el->cc_cnlist, &cii->c_cnhead);
61 /* remove a cache entry from the superblock list */
62 static void coda_ccremove(struct coda_cache *el)
64 ENTRY;
65 if ( ! list_empty(&el->cc_cclist) )
66 list_del(&el->cc_cclist);
67 else
68 printk("coda_cnremove: loose cc entry!");
71 /* remove a cache entry from the inode's list */
72 static void coda_cnremove(struct coda_cache *el)
74 ENTRY;
75 if ( ! list_empty(&el->cc_cnlist) )
76 list_del(&el->cc_cnlist);
77 else
78 printk("coda_cnremove: loose cn entry!");
81 /* create a new cache entry and enlist it */
82 static void coda_cache_create(struct inode *inode, int mask)
84 struct coda_inode_info *cii = ITOC(inode);
85 struct super_block *sb = inode->i_sb;
86 struct coda_cache *cc = NULL;
87 ENTRY;
89 CODA_ALLOC(cc, struct coda_cache *, sizeof(*cc));
91 if ( !cc ) {
92 printk("Out of memory in coda_cache_enter!\n");
93 return;
96 INIT_LIST_HEAD(&cc->cc_cclist);
97 INIT_LIST_HEAD(&cc->cc_cnlist);
99 coda_load_creds(&cc->cc_cred);
100 cc->cc_mask = mask;
101 coda_cninsert(cc, cii);
102 coda_ccinsert(cc, sb);
105 /* see if there is a match for the current
106 credentials already */
107 static struct coda_cache * coda_cache_find(struct inode *inode)
109 struct coda_inode_info *cii = ITOC(inode);
110 struct list_head *lh, *le;
111 struct coda_cache *cc = NULL;
113 le = lh = &cii->c_cnhead;
114 while( (le = le->next ) != lh ) {
115 /* compare name and creds */
116 cc = list_entry(le, struct coda_cache, cc_cnlist);
117 if ( !coda_cred_ok(&cc->cc_cred) )
118 continue;
119 CDEBUG(D_CACHE, "HIT for ino %ld\n", inode->i_ino );
120 return cc; /* cache hit */
122 return NULL;
125 /* create or extend an acl cache hit */
126 void coda_cache_enter(struct inode *inode, int mask)
128 struct coda_cache *cc;
130 cc = coda_cache_find(inode);
132 if ( cc ) {
133 cc->cc_mask |= mask;
134 } else {
135 coda_cache_create(inode, mask);
139 /* remove all cached acl matches from an inode */
140 void coda_cache_clear_inode(struct inode *inode)
142 struct list_head *lh, *le;
143 struct coda_inode_info *cii;
144 struct coda_cache *cc;
145 ENTRY;
147 if ( !inode ) {
148 CDEBUG(D_CACHE, "coda_cache_clear_inode: NULL inode\n");
149 return;
151 cii = ITOC(inode);
153 lh = le = &cii->c_cnhead;
154 while ( (le = le->next ) != lh ) {
155 cc = list_entry(le, struct coda_cache, cc_cnlist);
156 coda_cnremove(cc);
157 coda_ccremove(cc);
158 CODA_FREE(cc, sizeof(*cc));
162 /* remove all acl caches */
163 void coda_cache_clear_all(struct super_block *sb)
165 struct list_head *lh, *le;
166 struct coda_cache *cc;
167 struct coda_sb_info *sbi = coda_sbp(sb);
169 if ( !sbi ) {
170 printk("coda_cache_clear_all: NULL sbi\n");
171 return;
174 if ( list_empty(&sbi->sbi_cchead) )
175 return;
177 lh = le = &sbi->sbi_cchead;
178 while ( (le = le->next ) != lh ) {
179 cc = list_entry(le, struct coda_cache, cc_cclist);
180 coda_cnremove(cc);
181 coda_ccremove(cc);
182 CODA_FREE(cc, sizeof(*cc));
186 /* remove all acl caches for a principal */
187 void coda_cache_clear_cred(struct super_block *sb, struct coda_cred *cred)
189 struct list_head *lh, *le;
190 struct coda_cache *cc;
191 struct coda_sb_info *sbi = coda_sbp(sb);
193 if ( !sbi ) {
194 printk("coda_cache_clear_all: NULL sbi\n");
195 return;
198 if (list_empty(&sbi->sbi_cchead))
199 return;
201 lh = le = &sbi->sbi_cchead;
202 while ( (le = le->next ) != lh ) {
203 cc = list_entry(le, struct coda_cache, cc_cclist);
204 if ( coda_cred_eq(&cc->cc_cred, cred)) {
205 coda_cnremove(cc);
206 coda_ccremove(cc);
207 CODA_FREE(cc, sizeof(*cc));
213 /* check if the mask has been matched against the acl
214 already */
215 int coda_cache_check(struct inode *inode, int mask)
217 struct coda_inode_info *cii = ITOC(inode);
218 struct list_head *lh, *le;
219 struct coda_cache *cc = NULL;
221 le = lh = &cii->c_cnhead;
222 while( (le = le->next ) != lh ) {
223 /* compare name and creds */
224 cc = list_entry(le, struct coda_cache, cc_cnlist);
225 if ( (cc->cc_mask & mask) != mask )
226 continue;
227 if ( !coda_cred_ok(&cc->cc_cred) )
228 continue;
229 CDEBUG(D_CACHE, "HIT for ino %ld\n", inode->i_ino );
230 return 1; /* cache hit */
232 CDEBUG(D_CACHE, "MISS for ino %ld\n", inode->i_ino );
233 return 0;
237 /* Purging dentries and children */
238 /* The following routines drop dentries which are not
239 in use and flag dentries which are in use to be
240 zapped later.
242 The flags are detected by:
243 - coda_dentry_revalidate (for lookups) if the flag is C_PURGE
244 - coda_dentry_delete: to remove dentry from the cache when d_count
245 falls to zero
246 - an inode method coda_revalidate (for attributes) if the
247 flag is C_VATTR
251 Some of this is pretty scary: what can disappear underneath us?
252 - shrink_dcache_parent calls on purge_one_dentry which is safe:
253 it only purges children.
254 - dput is evil since it may recurse up the dentry tree
257 void coda_purge_dentries(struct inode *inode)
259 struct list_head *tmp, *head = &inode->i_dentry;
261 if (!inode)
262 return ;
264 /* better safe than sorry: dput could kill us */
265 iget(inode->i_sb, inode->i_ino);
266 /* catch the dentries later if some are still busy */
267 coda_flag_inode(inode, C_PURGE);
269 restart:
270 tmp = head;
271 while ((tmp = tmp->next) != head) {
272 struct dentry *dentry = list_entry(tmp, struct dentry, d_alias);
273 if (!dentry->d_count) {
274 CDEBUG(D_DOWNCALL,
275 "coda_free_dentries: freeing %s/%s, i_count=%d\n",
276 dentry->d_parent->d_name.name, dentry->d_name.name,
277 inode->i_count);
278 dget(dentry);
279 d_drop(dentry);
280 dput(dentry);
281 goto restart;
285 iput(inode);
288 /* this won't do any harm: just flag all children */
289 static void coda_flag_children(struct dentry *parent, int flag)
291 struct list_head *child;
292 struct dentry *de;
294 child = parent->d_subdirs.next;
295 while ( child != &parent->d_subdirs ) {
296 de = list_entry(child, struct dentry, d_child);
297 child = child->next;
298 /* don't know what to do with negative dentries */
299 if ( ! de->d_inode )
300 continue;
301 CDEBUG(D_DOWNCALL, "%d for %*s/%*s\n", flag,
302 de->d_name.len, de->d_name.name,
303 de->d_parent->d_name.len, de->d_parent->d_name.name);
304 coda_flag_inode(de->d_inode, flag);
306 return;
309 void coda_flag_inode_children(struct inode *inode, int flag)
311 struct list_head *alias;
312 struct dentry *alias_de;
314 ENTRY;
315 if ( !inode )
316 return;
318 if (list_empty(&inode->i_dentry))
319 return;
321 /* I believe that shrink_dcache_parent will not
322 remove dentries from the alias list. If it
323 does we are toast.
325 alias = inode->i_dentry.next;
326 while ( alias != &inode->i_dentry ) {
327 alias_de = list_entry(alias, struct dentry, d_alias);
328 coda_flag_children(alias_de, flag);
329 alias = alias->next;
330 shrink_dcache_parent(alias_de);
335 /* this will not zap the inode away */
336 void coda_flag_inode(struct inode *inode, int flag)
338 struct coda_inode_info *cii;
340 if ( !inode ) {
341 CDEBUG(D_CACHE, " no inode!\n");
342 return;
345 cii = ITOC(inode);
346 cii->c_flags |= flag;