summaryrefslogtreecommitdiffstats
path: root/fs/coda/cache.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1998-03-18 17:17:51 +0000
committerRalf Baechle <ralf@linux-mips.org>1998-03-18 17:17:51 +0000
commitf1382dc4850bb459d24a81c6cb0ef93ea7bd4a79 (patch)
tree225271a3d5dcd4e9dea5ee393556abd754c964b1 /fs/coda/cache.c
parent135b00fc2e90e605ac2a96b20b0ebd93851a3f89 (diff)
o Merge with Linux 2.1.90.
o Divide L1 cache sizes by 1024 before printing, makes the numbers a bit more credible ...
Diffstat (limited to 'fs/coda/cache.c')
-rw-r--r--fs/coda/cache.c196
1 files changed, 91 insertions, 105 deletions
diff --git a/fs/coda/cache.c b/fs/coda/cache.c
index 7673bfbdd..cdf586507 100644
--- a/fs/coda/cache.c
+++ b/fs/coda/cache.c
@@ -24,16 +24,22 @@
#include <linux/coda_fs_i.h>
#include <linux/coda_cache.h>
-/* Keep various stats */
-struct cfsnc_statistics cfsnc_stat;
+static void coda_ccinsert(struct coda_cache *el, struct super_block *sb);
+static void coda_cninsert(struct coda_cache *el, struct coda_inode_info *cii);
+static void coda_ccremove(struct coda_cache *el);
+static void coda_cnremove(struct coda_cache *el);
+static void coda_cache_create(struct inode *inode, int mask);
+static struct coda_cache * coda_cache_find(struct inode *inode);
-/* we need to call INIT_LIST_HEAD on cnp->c_cnhead and sbi->sbi_cchead */
+/* Keep various stats */
+struct cfsnc_statistics cfsnc_stat;
-void coda_ccinsert(struct coda_cache *el, struct super_block *sb)
+/* insert a acl-cache entry in sb list */
+static void coda_ccinsert(struct coda_cache *el, struct super_block *sb)
{
struct coda_sb_info *sbi = coda_sbp(sb);
-ENTRY;
+ ENTRY;
if ( !sbi || !el) {
printk("coda_ccinsert: NULL sbi or el!\n");
return ;
@@ -42,17 +48,19 @@ ENTRY;
list_add(&el->cc_cclist, &sbi->sbi_cchead);
}
-void coda_cninsert(struct coda_cache *el, struct coda_inode_info *cnp)
+/* insert a acl-cache entry in the inode list */
+static void coda_cninsert(struct coda_cache *el, struct coda_inode_info *cii)
{
-ENTRY;
- if ( !cnp || !el) {
- printk("coda_cninsert: NULL cnp or el!\n");
+ ENTRY;
+ if ( !cii || !el) {
+ printk("coda_cninsert: NULL cii or el!\n");
return ;
}
- list_add(&el->cc_cnlist, &cnp->c_cnhead);
+ list_add(&el->cc_cnlist, &cii->c_cnhead);
}
-void coda_ccremove(struct coda_cache *el)
+/* remove a cache entry from the superblock list */
+static void coda_ccremove(struct coda_cache *el)
{
ENTRY;
if (el->cc_cclist.next && el->cc_cclist.prev)
@@ -61,7 +69,8 @@ void coda_ccremove(struct coda_cache *el)
printk("coda_cnremove: trying to remove 0 entry!");
}
-void coda_cnremove(struct coda_cache *el)
+/* remove a cache entry from the inode's list */
+static void coda_cnremove(struct coda_cache *el)
{
ENTRY;
if (el->cc_cnlist.next && el->cc_cnlist.prev)
@@ -70,10 +79,10 @@ void coda_cnremove(struct coda_cache *el)
printk("coda_cnremove: trying to remove 0 entry!");
}
-
-void coda_cache_create(struct inode *inode, int mask)
+/* create a new cache entry and enlist it */
+static void coda_cache_create(struct inode *inode, int mask)
{
- struct coda_inode_info *cnp = ITOC(inode);
+ struct coda_inode_info *cii = ITOC(inode);
struct super_block *sb = inode->i_sb;
struct coda_cache *cc = NULL;
ENTRY;
@@ -85,17 +94,19 @@ void coda_cache_create(struct inode *inode, int mask)
}
coda_load_creds(&cc->cc_cred);
cc->cc_mask = mask;
- coda_cninsert(cc, cnp);
+ coda_cninsert(cc, cii);
coda_ccinsert(cc, sb);
}
-struct coda_cache * coda_cache_find(struct inode *inode)
+/* see if there is a match for the current
+ credentials already */
+static struct coda_cache * coda_cache_find(struct inode *inode)
{
- struct coda_inode_info *cnp = ITOC(inode);
+ struct coda_inode_info *cii = ITOC(inode);
struct list_head *lh, *le;
struct coda_cache *cc = NULL;
- le = lh = &cnp->c_cnhead;
+ le = lh = &cii->c_cnhead;
while( (le = le->next ) != lh ) {
/* compare name and creds */
cc = list_entry(le, struct coda_cache, cc_cnlist);
@@ -107,6 +118,7 @@ struct coda_cache * coda_cache_find(struct inode *inode)
return NULL;
}
+/* create or extend an acl cache hit */
void coda_cache_enter(struct inode *inode, int mask)
{
struct coda_cache *cc;
@@ -120,17 +132,21 @@ void coda_cache_enter(struct inode *inode, int mask)
}
}
-void coda_cache_clear_cnp(struct coda_inode_info *cnp)
+/* remove all cached acl matches from an inode */
+void coda_cache_clear_inode(struct inode *inode)
{
struct list_head *lh, *le;
+ struct coda_inode_info *cii;
struct coda_cache *cc;
+ ENTRY;
- if ( !cnp ) {
- printk("coda_cache_cnp_clear: NULL cnode\n");
+ if ( !inode ) {
+ CDEBUG(D_CACHE, "coda_cache_clear_inode: NULL inode\n");
return;
}
+ cii = ITOC(inode);
- lh = le = &cnp->c_cnhead;
+ lh = le = &cii->c_cnhead;
while ( (le = le->next ) != lh ) {
cc = list_entry(le, struct coda_cache, cc_cnlist);
coda_cnremove(cc);
@@ -139,6 +155,7 @@ void coda_cache_clear_cnp(struct coda_inode_info *cnp)
}
}
+/* remove all acl caches */
void coda_cache_clear_all(struct super_block *sb)
{
struct list_head *lh, *le;
@@ -150,6 +167,9 @@ void coda_cache_clear_all(struct super_block *sb)
return;
}
+ if ( list_empty(&sbi->sbi_cchead) )
+ return;
+
lh = le = &sbi->sbi_cchead;
while ( (le = le->next ) != lh ) {
cc = list_entry(le, struct coda_cache, cc_cclist);
@@ -159,6 +179,7 @@ void coda_cache_clear_all(struct super_block *sb)
}
}
+/* remove all acl caches for a principal */
void coda_cache_clear_cred(struct super_block *sb, struct coda_cred *cred)
{
struct list_head *lh, *le;
@@ -170,6 +191,9 @@ void coda_cache_clear_cred(struct super_block *sb, struct coda_cred *cred)
return;
}
+ if (list_empty(&sbi->sbi_cchead))
+ return;
+
lh = le = &sbi->sbi_cchead;
while ( (le = le->next ) != lh ) {
cc = list_entry(le, struct coda_cache, cc_cclist);
@@ -180,15 +204,17 @@ void coda_cache_clear_cred(struct super_block *sb, struct coda_cred *cred)
}
}
}
-
+
+/* check if the mask has been matched against the acl
+ already */
int coda_cache_check(struct inode *inode, int mask)
{
- struct coda_inode_info *cnp = ITOC(inode);
+ struct coda_inode_info *cii = ITOC(inode);
struct list_head *lh, *le;
struct coda_cache *cc = NULL;
- le = lh = &cnp->c_cnhead;
+ le = lh = &cii->c_cnhead;
while( (le = le->next ) != lh ) {
/* compare name and creds */
cc = list_entry(le, struct coda_cache, cc_cnlist);
@@ -204,110 +230,70 @@ int coda_cache_check(struct inode *inode, int mask)
}
-/* DENTRY related stuff */
+/* DCACHE & ZAPPING related stuff */
-/* when the dentry count falls to 0 this is called. If Venus has
- asked for it to be flushed, we take it out of the dentry hash
- table with d_drop */
-
-static void coda_flag_children(struct dentry *parent)
+/* the following routines set flags in the inodes. They are
+ detected by:
+ - a dentry method: coda_dentry_revalidate (for lookups)
+ if the flag is C_PURGE
+ - an inode method coda_revalidate (for attributes) if the
+ flag is C_ATTR
+*/
+static void coda_flag_children(struct dentry *parent, int flag)
{
struct list_head *child;
- struct coda_inode_info *cnp;
struct dentry *de;
child = parent->d_subdirs.next;
while ( child != &parent->d_subdirs ) {
de = list_entry(child, struct dentry, d_child);
- cnp = ITOC(de->d_inode);
- if (cnp)
- cnp->c_flags |= C_ZAPFID;
- CDEBUG(D_CACHE, "ZAPFID for %s\n", coda_f2s(&cnp->c_fid));
-
+ coda_flag_inode(de->d_inode, flag);
+ CDEBUG(D_CACHE, "%d for %*s/%*s\n", flag,
+ de->d_name.len, de->d_name.name,
+ de->d_parent->d_name.len, de->d_parent->d_name.name);
child = child->next;
+ if ( !de->d_inode )
+ d_drop(de);
}
return;
}
-/* flag dentry and possibly children of a dentry with C_ZAPFID */
-void coda_dentry_delete(struct dentry *dentry)
-{
- struct inode *inode = dentry->d_inode;
- struct coda_inode_info *cnp = NULL;
- ENTRY;
- if (inode) {
- cnp = ITOC(inode);
- if ( cnp )
- CHECK_CNODE(cnp);
- } else {
- CDEBUG(D_CACHE, "No inode for dentry_delete!\n");
- return;
- }
-
-
- if ( !cnp ) {
- printk("No cnode for dentry_delete!\n");
- return;
- }
-
- if ( cnp->c_flags & (C_ZAPFID | C_ZAPDIR) )
- d_drop(dentry);
- if ( (cnp->c_flags & C_ZAPDIR) && S_ISDIR(inode->i_mode) ) {
- coda_flag_children(dentry);
- }
- return;
-}
-
-static void coda_zap_cnode(struct coda_inode_info *cnp, int flags)
+void coda_flag_alias_children(struct inode *inode, int flag)
{
- cnp->c_flags |= flags;
- coda_cache_clear_cnp(cnp);
+ struct list_head *alias;
+ struct dentry *alias_de;
+
+ if ( !inode )
+ return;
+ alias = inode->i_dentry.next;
+ while ( alias != &inode->i_dentry ) {
+ alias_de = list_entry(alias, struct dentry, d_alias);
+ if ( !alias_de ) {
+ printk("Corrupt alias list for %*s\n",
+ alias_de->d_name.len, alias_de->d_name.name);
+ return;
+ }
+ coda_flag_children(alias_de, flag);
+ alias= alias->next;
+ }
}
-
-
-/* the dache will notice the flags and drop entries (possibly with
- children) the moment they are no longer in use */
-void coda_zapfid(struct ViceFid *fid, struct super_block *sb, int flag)
+void coda_flag_inode(struct inode *inode, int flag)
{
- struct inode *inode = NULL;
- struct coda_inode_info *cnp;
+ struct coda_inode_info *cii;
- ENTRY;
-
- if ( !sb ) {
- printk("coda_zapfid: no sb!\n");
+ if ( !inode ) {
+ CDEBUG(D_CACHE, " no inode!\n");
return;
}
+ cii = ITOC(inode);
+ cii->c_flags |= flag;
+}
- if ( !fid ) {
- printk("coda_zapfid: no fid!\n");
- return;
- }
- if ( coda_fid_is_volroot(fid) ) {
- struct list_head *lh, *le;
- struct coda_sb_info *sbi = coda_sbp(sb);
- le = lh = &sbi->sbi_volroothead;
- while ( (le = le->next) != lh ) {
- cnp = list_entry(le, struct coda_inode_info, c_volrootlist);
- if ( cnp->c_fid.Volume == fid->Volume)
- coda_zap_cnode(cnp, flag);
- }
- return;
- }
- inode = coda_fid_to_inode(fid, sb);
- if ( !inode ) {
- CDEBUG(D_CACHE, "coda_zapfid: no inode!\n");
- return;
- }
- cnp = ITOC(inode);
- coda_zap_cnode(cnp, flag);
-}
-
int
cfsnc_nc_info(char *buffer, char **start, off_t offset, int length, int dummy)