summaryrefslogtreecommitdiffstats
path: root/fs/coda/cache.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/coda/cache.c')
-rw-r--r--fs/coda/cache.c172
1 files changed, 32 insertions, 140 deletions
diff --git a/fs/coda/cache.c b/fs/coda/cache.c
index e837db96a..db7fbb4ec 100644
--- a/fs/coda/cache.c
+++ b/fs/coda/cache.c
@@ -24,168 +24,60 @@
#include <linux/coda_fs_i.h>
#include <linux/coda_cache.h>
-/* create a new acl cache entry and enlist it */
-static struct coda_cache *coda_cache_create(struct inode *inode)
-{
- struct coda_inode_info *cii = ITOC(inode);
- struct coda_sb_info *sbi = coda_sbp(inode->i_sb);
- struct coda_cache *cc = NULL;
- ENTRY;
-
- if ( !sbi || !cii ) {
- printk("coda_cache_create: NULL sbi or cii!\n");
- return NULL;
- }
-
- CODA_ALLOC(cc, struct coda_cache *, sizeof(*cc));
-
- if ( !cc ) {
- printk("Out of memory in coda_cache_create!\n");
- return NULL;
- }
-
- coda_load_creds(&cc->cc_cred);
- cc->cc_mask = 0;
-
- INIT_LIST_HEAD(&cc->cc_cclist);
- INIT_LIST_HEAD(&cc->cc_cnlist);
- list_add(&cc->cc_cclist, &sbi->sbi_cchead);
- list_add(&cc->cc_cnlist, &cii->c_cnhead);
-
- return cc;
-}
-
-/* destroy an acl cache entry */
-static void coda_cache_destroy(struct coda_cache *el)
-{
- ENTRY;
- if (list_empty(&el->cc_cclist) || list_empty(&el->cc_cnlist)) {
- printk("coda_cache_destroy: loose entry!");
- return;
- }
- list_del(&el->cc_cclist);
- list_del(&el->cc_cnlist);
- CODA_FREE(el, sizeof(struct coda_cache));
-}
-
-/* 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 *cii = ITOC(inode);
- struct list_head *le;
- struct coda_cache *cc = NULL;
-
- list_for_each(le, &cii->c_cnhead)
- {
- /* compare name and creds */
- cc = list_entry(le, struct coda_cache, cc_cnlist);
- if ( !coda_cred_ok(&cc->cc_cred) )
- continue;
- CDEBUG(D_CACHE, "HIT for ino %ld\n", inode->i_ino );
- return cc; /* cache hit */
- }
- return NULL;
-}
-
-/* create or extend an acl cache hit */
+/* replace or extend an acl cache hit */
void coda_cache_enter(struct inode *inode, int mask)
{
- struct coda_cache *cc;
-
- cc = coda_cache_find(inode);
+ struct coda_inode_info *cii = ITOC(inode);
+ ENTRY;
- if (!cc)
- cc = coda_cache_create(inode);
- if (cc)
- cc->cc_mask |= mask;
+ if ( !coda_cred_ok(&cii->c_cached_cred) ) {
+ coda_load_creds(&cii->c_cached_cred);
+ cii->c_cached_perm = mask;
+ } else
+ cii->c_cached_perm |= mask;
}
-/* remove all cached acl matches from an inode */
+/* remove cached acl from an inode */
void coda_cache_clear_inode(struct inode *inode)
{
- struct list_head *le;
- struct coda_inode_info *cii;
- struct coda_cache *cc;
+ struct coda_inode_info *cii = ITOC(inode);
ENTRY;
-
- if ( !inode ) {
- CDEBUG(D_CACHE, "coda_cache_clear_inode: NULL inode\n");
- return;
- }
- cii = ITOC(inode);
-
- le = cii->c_cnhead.next;
- while ( le != &cii->c_cnhead ) {
- cc = list_entry(le, struct coda_cache, cc_cnlist);
- le = le->next;
- coda_cache_destroy(cc);
- }
+ cii->c_cached_perm = 0;
}
-/* remove all acl caches */
-void coda_cache_clear_all(struct super_block *sb)
+/* remove all acl caches for a principal (or all principals when cred == NULL)*/
+void coda_cache_clear_all(struct super_block *sb, struct coda_cred *cred)
{
- struct list_head *le;
- struct coda_cache *cc;
- struct coda_sb_info *sbi = coda_sbp(sb);
+ struct coda_sb_info *sbi;
+ struct coda_inode_info *cii;
+ struct list_head *tmp;
- if ( !sbi ) {
- printk("coda_cache_clear_all: NULL sbi\n");
- return;
- }
-
- le = sbi->sbi_cchead.next;
- while ( le != &sbi->sbi_cchead ) {
- cc = list_entry(le, struct coda_cache, cc_cclist);
- le = le->next;
- coda_cache_destroy(cc);
- }
-}
+ ENTRY;
+ sbi = coda_sbp(sb);
+ if (!sbi) BUG();
-/* remove all acl caches for a principal */
-void coda_cache_clear_cred(struct super_block *sb, struct coda_cred *cred)
-{
- struct list_head *le;
- struct coda_cache *cc;
- struct coda_sb_info *sbi = coda_sbp(sb);
+ list_for_each(tmp, &sbi->sbi_cihead)
+ {
+ cii = list_entry(tmp, struct coda_inode_info, c_cilist);
+ if ( cii->c_magic != CODA_CNODE_MAGIC ) BUG();
- if ( !sbi ) {
- printk("coda_cache_clear_all: NULL sbi\n");
- return;
- }
-
- le = sbi->sbi_cchead.next;
- while ( le != &sbi->sbi_cchead ) {
- cc = list_entry(le, struct coda_cache, cc_cclist);
- le = le->next;
- if ( coda_cred_eq(&cc->cc_cred, cred))
- coda_cache_destroy(cc);
+ if (!cred || coda_cred_eq(cred, &cii->c_cached_cred))
+ cii->c_cached_perm = 0;
}
}
-/* check if the mask has been matched against the acl
- already */
+/* check if the mask has been matched against the acl already */
int coda_cache_check(struct inode *inode, int mask)
{
struct coda_inode_info *cii = ITOC(inode);
- struct list_head *le;
- struct coda_cache *cc = NULL;
+ int hit;
- list_for_each(le, &cii->c_cnhead)
- {
- /* compare name and creds */
- cc = list_entry(le, struct coda_cache, cc_cnlist);
- if ( (cc->cc_mask & mask) != mask )
- continue;
- if ( !coda_cred_ok(&cc->cc_cred) )
- continue;
- CDEBUG(D_CACHE, "HIT for ino %ld\n", inode->i_ino );
- return 1; /* cache hit */
- }
- CDEBUG(D_CACHE, "MISS for ino %ld\n", inode->i_ino );
- return 0;
+ hit = ((mask & cii->c_cached_perm) == mask) &&
+ coda_cred_ok(&cii->c_cached_cred);
+
+ CDEBUG(D_CACHE, "%s for ino %ld\n", hit ? "HIT" : "MISS", inode->i_ino);
+ return hit;
}