Ok. I didn't make 2.4.0 in 2000. Tough. I tried, but we had some
[davej-history.git] / fs / coda / cache.c
blobdb7fbb4eca821e0f51e798e5c65cca555744c159
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 /* replace or extend an acl cache hit */
28 void coda_cache_enter(struct inode *inode, int mask)
30 struct coda_inode_info *cii = ITOC(inode);
31 ENTRY;
33 if ( !coda_cred_ok(&cii->c_cached_cred) ) {
34 coda_load_creds(&cii->c_cached_cred);
35 cii->c_cached_perm = mask;
36 } else
37 cii->c_cached_perm |= mask;
40 /* remove cached acl from an inode */
41 void coda_cache_clear_inode(struct inode *inode)
43 struct coda_inode_info *cii = ITOC(inode);
44 ENTRY;
45 cii->c_cached_perm = 0;
48 /* remove all acl caches for a principal (or all principals when cred == NULL)*/
49 void coda_cache_clear_all(struct super_block *sb, struct coda_cred *cred)
51 struct coda_sb_info *sbi;
52 struct coda_inode_info *cii;
53 struct list_head *tmp;
55 ENTRY;
56 sbi = coda_sbp(sb);
57 if (!sbi) BUG();
59 list_for_each(tmp, &sbi->sbi_cihead)
61 cii = list_entry(tmp, struct coda_inode_info, c_cilist);
62 if ( cii->c_magic != CODA_CNODE_MAGIC ) BUG();
64 if (!cred || coda_cred_eq(cred, &cii->c_cached_cred))
65 cii->c_cached_perm = 0;
70 /* check if the mask has been matched against the acl already */
71 int coda_cache_check(struct inode *inode, int mask)
73 struct coda_inode_info *cii = ITOC(inode);
74 int hit;
76 hit = ((mask & cii->c_cached_perm) == mask) &&
77 coda_cred_ok(&cii->c_cached_cred);
79 CDEBUG(D_CACHE, "%s for ino %ld\n", hit ? "HIT" : "MISS", inode->i_ino);
80 return hit;
84 /* Purging dentries and children */
85 /* The following routines drop dentries which are not
86 in use and flag dentries which are in use to be
87 zapped later.
89 The flags are detected by:
90 - coda_dentry_revalidate (for lookups) if the flag is C_PURGE
91 - coda_dentry_delete: to remove dentry from the cache when d_count
92 falls to zero
93 - an inode method coda_revalidate (for attributes) if the
94 flag is C_VATTR
97 /*
98 Some of this is pretty scary: what can disappear underneath us?
99 - shrink_dcache_parent calls on purge_one_dentry which is safe:
100 it only purges children.
101 - dput is evil since it may recurse up the dentry tree
104 void coda_purge_dentries(struct inode *inode)
106 if (!inode)
107 return ;
109 /* better safe than sorry: dput could kill us */
110 iget(inode->i_sb, inode->i_ino);
111 /* catch the dentries later if some are still busy */
112 coda_flag_inode(inode, C_PURGE);
113 d_prune_aliases(inode);
114 iput(inode);
117 /* this won't do any harm: just flag all children */
118 static void coda_flag_children(struct dentry *parent, int flag)
120 struct list_head *child;
121 struct dentry *de;
123 spin_lock(&dcache_lock);
124 list_for_each(child, &parent->d_subdirs)
126 de = list_entry(child, struct dentry, d_child);
127 /* don't know what to do with negative dentries */
128 if ( ! de->d_inode )
129 continue;
130 CDEBUG(D_DOWNCALL, "%d for %*s/%*s\n", flag,
131 de->d_name.len, de->d_name.name,
132 de->d_parent->d_name.len, de->d_parent->d_name.name);
133 coda_flag_inode(de->d_inode, flag);
135 spin_unlock(&dcache_lock);
136 return;
139 void coda_flag_inode_children(struct inode *inode, int flag)
141 struct dentry *alias_de;
143 ENTRY;
144 if ( !inode || !S_ISDIR(inode->i_mode))
145 return;
147 alias_de = d_find_alias(inode);
148 if (!alias_de)
149 return;
150 coda_flag_children(alias_de, flag);
151 shrink_dcache_parent(alias_de);
152 dput(alias_de);