Commit 64353a2b authored by Jan Harkes's avatar Jan Harkes Committed by Linus Torvalds

[PATCH] Coda updates [2/5]

Use a global 'epoch' counter to invalidate cached permissions instead of
traversing a racy linked list of all known Coda inodes.
parent 87653883
...@@ -23,11 +23,14 @@ ...@@ -23,11 +23,14 @@
#include <linux/coda_fs_i.h> #include <linux/coda_fs_i.h>
#include <linux/coda_cache.h> #include <linux/coda_cache.h>
static atomic_t permission_epoch = ATOMIC_INIT(0);
/* replace or extend an acl cache hit */ /* replace or extend an acl cache hit */
void coda_cache_enter(struct inode *inode, int mask) void coda_cache_enter(struct inode *inode, int mask)
{ {
struct coda_inode_info *cii = ITOC(inode); struct coda_inode_info *cii = ITOC(inode);
cii->c_cached_epoch = atomic_read(&permission_epoch);
if ( !coda_cred_ok(&cii->c_cached_cred) ) { if ( !coda_cred_ok(&cii->c_cached_cred) ) {
coda_load_creds(&cii->c_cached_cred); coda_load_creds(&cii->c_cached_cred);
cii->c_cached_perm = mask; cii->c_cached_perm = mask;
...@@ -42,22 +45,15 @@ void coda_cache_clear_inode(struct inode *inode) ...@@ -42,22 +45,15 @@ void coda_cache_clear_inode(struct inode *inode)
cii->c_cached_perm = 0; cii->c_cached_perm = 0;
} }
/* remove all acl caches for a principal (or all principals when cred == NULL)*/ /* remove all acl caches */
void coda_cache_clear_all(struct super_block *sb, struct coda_cred *cred) void coda_cache_clear_all(struct super_block *sb)
{ {
struct coda_sb_info *sbi; struct coda_sb_info *sbi;
struct coda_inode_info *cii;
struct list_head *tmp;
sbi = coda_sbp(sb); sbi = coda_sbp(sb);
if (!sbi) BUG(); if (!sbi) BUG();
list_for_each(tmp, &sbi->sbi_cihead) atomic_inc(&permission_epoch);
{
cii = list_entry(tmp, struct coda_inode_info, c_cilist);
if (!cred || coda_cred_eq(cred, &cii->c_cached_cred))
cii->c_cached_perm = 0;
}
} }
...@@ -67,8 +63,9 @@ int coda_cache_check(struct inode *inode, int mask) ...@@ -67,8 +63,9 @@ int coda_cache_check(struct inode *inode, int mask)
struct coda_inode_info *cii = ITOC(inode); struct coda_inode_info *cii = ITOC(inode);
int hit; int hit;
hit = ((mask & cii->c_cached_perm) == mask) && hit = (mask & cii->c_cached_perm) == mask &&
coda_cred_ok(&cii->c_cached_cred); coda_cred_ok(&cii->c_cached_cred) &&
cii->c_cached_epoch == atomic_read(&permission_epoch);
return hit; return hit;
} }
......
...@@ -64,7 +64,6 @@ struct inode * coda_iget(struct super_block * sb, ViceFid * fid, ...@@ -64,7 +64,6 @@ struct inode * coda_iget(struct super_block * sb, ViceFid * fid,
{ {
struct inode *inode; struct inode *inode;
struct coda_inode_info *cii; struct coda_inode_info *cii;
struct coda_sb_info *sbi = coda_sbp(sb);
unsigned long hash = coda_f2i(fid); unsigned long hash = coda_f2i(fid);
inode = iget5_locked(sb, hash, coda_test_inode, coda_set_inode, fid); inode = iget5_locked(sb, hash, coda_test_inode, coda_set_inode, fid);
...@@ -77,7 +76,6 @@ struct inode * coda_iget(struct super_block * sb, ViceFid * fid, ...@@ -77,7 +76,6 @@ struct inode * coda_iget(struct super_block * sb, ViceFid * fid,
/* we still need to set i_ino for things like stat(2) */ /* we still need to set i_ino for things like stat(2) */
inode->i_ino = hash; inode->i_ino = hash;
cii->c_mapcount = 0; cii->c_mapcount = 0;
list_add(&cii->c_cilist, &sbi->sbi_cihead);
unlock_new_inode(inode); unlock_new_inode(inode);
} }
......
...@@ -46,7 +46,6 @@ static struct inode *coda_alloc_inode(struct super_block *sb) ...@@ -46,7 +46,6 @@ static struct inode *coda_alloc_inode(struct super_block *sb)
return NULL; return NULL;
memset(&ei->c_fid, 0, sizeof(struct ViceFid)); memset(&ei->c_fid, 0, sizeof(struct ViceFid));
ei->c_flags = 0; ei->c_flags = 0;
INIT_LIST_HEAD(&ei->c_cilist);
memset(&ei->c_cached_cred, 0, sizeof(struct coda_cred)); memset(&ei->c_cached_cred, 0, sizeof(struct coda_cred));
ei->c_cached_perm = 0; ei->c_cached_perm = 0;
return &ei->vfs_inode; return &ei->vfs_inode;
...@@ -170,7 +169,6 @@ static int coda_fill_super(struct super_block *sb, void *data, int silent) ...@@ -170,7 +169,6 @@ static int coda_fill_super(struct super_block *sb, void *data, int silent)
vc->vc_sb = sb; vc->vc_sb = sb;
sbi->sbi_vcomm = vc; sbi->sbi_vcomm = vc;
INIT_LIST_HEAD(&sbi->sbi_cihead);
sb->s_fs_info = sbi; sb->s_fs_info = sbi;
sb->s_blocksize = 1024; /* XXXXX what do we put here?? */ sb->s_blocksize = 1024; /* XXXXX what do we put here?? */
...@@ -217,7 +215,6 @@ static void coda_put_super(struct super_block *sb) ...@@ -217,7 +215,6 @@ static void coda_put_super(struct super_block *sb)
sbi = coda_sbp(sb); sbi = coda_sbp(sb);
sbi->sbi_vcomm->vc_sb = NULL; sbi->sbi_vcomm->vc_sb = NULL;
list_del_init(&sbi->sbi_cihead);
printk("Coda: Bye bye.\n"); printk("Coda: Bye bye.\n");
kfree(sbi); kfree(sbi);
...@@ -225,9 +222,6 @@ static void coda_put_super(struct super_block *sb) ...@@ -225,9 +222,6 @@ static void coda_put_super(struct super_block *sb)
static void coda_clear_inode(struct inode *inode) static void coda_clear_inode(struct inode *inode)
{ {
struct coda_inode_info *cii = ITOC(inode);
list_del_init(&cii->c_cilist);
coda_cache_clear_inode(inode); coda_cache_clear_inode(inode);
} }
......
...@@ -819,19 +819,14 @@ int coda_downcall(int opcode, union outputArgs * out, struct super_block *sb) ...@@ -819,19 +819,14 @@ int coda_downcall(int opcode, union outputArgs * out, struct super_block *sb)
switch (opcode) { switch (opcode) {
case CODA_FLUSH : { case CODA_FLUSH : {
coda_cache_clear_all(sb, NULL); coda_cache_clear_all(sb);
shrink_dcache_sb(sb); shrink_dcache_sb(sb);
coda_flag_inode(sb->s_root->d_inode, C_FLUSH); coda_flag_inode(sb->s_root->d_inode, C_FLUSH);
return(0); return(0);
} }
case CODA_PURGEUSER : { case CODA_PURGEUSER : {
struct coda_cred *cred = &out->coda_purgeuser.cred; coda_cache_clear_all(sb);
if ( !cred ) {
printk("PURGEUSER: null cred!\n");
return 0;
}
coda_cache_clear_all(sb, cred);
return(0); return(0);
} }
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
/* credential cache */ /* credential cache */
void coda_cache_enter(struct inode *inode, int mask); void coda_cache_enter(struct inode *inode, int mask);
void coda_cache_clear_inode(struct inode *); void coda_cache_clear_inode(struct inode *);
void coda_cache_clear_all(struct super_block *sb, struct coda_cred *cred); void coda_cache_clear_all(struct super_block *sb);
int coda_cache_check(struct inode *inode, int mask); int coda_cache_check(struct inode *inode, int mask);
/* for downcalls and attributes and lookups */ /* for downcalls and attributes and lookups */
......
...@@ -21,6 +21,7 @@ struct coda_inode_info { ...@@ -21,6 +21,7 @@ struct coda_inode_info {
u_short c_flags; /* flags (see below) */ u_short c_flags; /* flags (see below) */
struct list_head c_cilist; /* list of all coda inodes */ struct list_head c_cilist; /* list of all coda inodes */
unsigned int c_mapcount; /* nr of times this inode is mapped */ unsigned int c_mapcount; /* nr of times this inode is mapped */
unsigned int c_cached_epoch;
struct coda_cred c_cached_cred; /* credentials of cached perms */ struct coda_cred c_cached_cred; /* credentials of cached perms */
unsigned int c_cached_perm; /* cached access permissions */ unsigned int c_cached_perm; /* cached access permissions */
struct inode vfs_inode; struct inode vfs_inode;
......
...@@ -11,7 +11,6 @@ struct kstatfs; ...@@ -11,7 +11,6 @@ struct kstatfs;
struct coda_sb_info struct coda_sb_info
{ {
struct venus_comm *sbi_vcomm; struct venus_comm *sbi_vcomm;
struct list_head sbi_cihead;
}; };
/* communication pending/processing queues */ /* communication pending/processing queues */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment