File: /usr/src/linux/fs/coda/cache.c

1     /*
2      * Cache operations for Coda.
3      * For Linux 2.1: (C) 1997 Carnegie Mellon University
4      * For Linux 2.3: (C) 2000 Carnegie Mellon University
5      *
6      * Carnegie Mellon encourages users of this code to contribute improvements
7      * to the Coda project http://www.coda.cs.cmu.edu/ <coda@cs.cmu.edu>.
8      */
9     
10     #include <linux/types.h>
11     #include <linux/kernel.h>
12     #include <linux/sched.h>
13     #include <linux/fs.h>
14     #include <linux/stat.h>
15     #include <linux/errno.h>
16     #include <linux/locks.h>
17     #include <asm/segment.h>
18     #include <asm/uaccess.h>
19     #include <linux/string.h>
20     #include <linux/list.h>
21     
22     #include <linux/coda.h>
23     #include <linux/coda_linux.h>
24     #include <linux/coda_psdev.h>
25     #include <linux/coda_fs_i.h>
26     #include <linux/coda_cache.h>
27     
28     /* replace or extend an acl cache hit */
29     void coda_cache_enter(struct inode *inode, int mask)
30     {
31     	struct coda_inode_info *cii = ITOC(inode);
32             ENTRY;
33     
34             if ( !coda_cred_ok(&cii->c_cached_cred) ) {
35                     coda_load_creds(&cii->c_cached_cred);
36                     cii->c_cached_perm = mask;
37             } else
38                     cii->c_cached_perm |= mask;
39     }
40     
41     /* remove cached acl from an inode */
42     void coda_cache_clear_inode(struct inode *inode)
43     {
44     	struct coda_inode_info *cii = ITOC(inode);
45     	ENTRY;
46             cii->c_cached_perm = 0;
47     }
48     
49     /* remove all acl caches for a principal (or all principals when cred == NULL)*/
50     void coda_cache_clear_all(struct super_block *sb, struct coda_cred *cred)
51     {
52             struct coda_sb_info *sbi;
53             struct coda_inode_info *cii;
54             struct list_head *tmp;
55     
56             ENTRY;
57             sbi = coda_sbp(sb);
58             if (!sbi) BUG();
59     
60             list_for_each(tmp, &sbi->sbi_cihead)
61             {
62     		cii = list_entry(tmp, struct coda_inode_info, c_cilist);
63                     if (!cred || coda_cred_eq(cred, &cii->c_cached_cred))
64                             cii->c_cached_perm = 0;
65     	}
66     }
67     
68     
69     /* check if the mask has been matched against the acl already */
70     int coda_cache_check(struct inode *inode, int mask)
71     {
72     	struct coda_inode_info *cii = ITOC(inode);
73             int hit;
74     	
75             hit = ((mask & cii->c_cached_perm) == mask) &&
76                     coda_cred_ok(&cii->c_cached_cred);
77     
78             CDEBUG(D_CACHE, "%s for ino %ld\n", hit ? "HIT" : "MISS", inode->i_ino);
79             return hit;
80     }
81     
82     
83     /* Purging dentries and children */
84     /* The following routines drop dentries which are not
85        in use and flag dentries which are in use to be 
86        zapped later.
87     
88        The flags are detected by:
89        - coda_dentry_revalidate (for lookups) if the flag is C_PURGE
90        - coda_dentry_delete: to remove dentry from the cache when d_count
91          falls to zero
92        - an inode method coda_revalidate (for attributes) if the 
93          flag is C_VATTR
94     */
95     
96     /* this won't do any harm: just flag all children */
97     static void coda_flag_children(struct dentry *parent, int flag)
98     {
99     	struct list_head *child;
100     	struct dentry *de;
101     
102     	spin_lock(&dcache_lock);
103     	list_for_each(child, &parent->d_subdirs)
104     	{
105     		de = list_entry(child, struct dentry, d_child);
106     		/* don't know what to do with negative dentries */
107     		if ( ! de->d_inode ) 
108     			continue;
109     		CDEBUG(D_DOWNCALL, "%d for %*s/%*s\n", flag, 
110     		       de->d_name.len, de->d_name.name, 
111     		       de->d_parent->d_name.len, de->d_parent->d_name.name);
112     		coda_flag_inode(de->d_inode, flag);
113     	}
114     	spin_unlock(&dcache_lock);
115     	return; 
116     }
117     
118     void coda_flag_inode_children(struct inode *inode, int flag)
119     {
120     	struct dentry *alias_de;
121     
122     	ENTRY;
123     	if ( !inode || !S_ISDIR(inode->i_mode)) 
124     		return; 
125     
126     	alias_de = d_find_alias(inode);
127     	if (!alias_de)
128     		return;
129     	coda_flag_children(alias_de, flag);
130     	shrink_dcache_parent(alias_de);
131     	dput(alias_de);
132     }
133     
134