From 64353a2bae9026326af3f34b87918c2e94120b8e Mon Sep 17 00:00:00 2001 From: Jan Harkes Date: Tue, 16 Sep 2003 03:33:13 -0700 Subject: [PATCH] [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. --- fs/coda/cache.c | 21 +++++++++------------ fs/coda/cnode.c | 2 -- fs/coda/inode.c | 6 ------ fs/coda/upcall.c | 9 ++------- include/linux/coda_cache.h | 2 +- include/linux/coda_fs_i.h | 1 + include/linux/coda_psdev.h | 1 - 7 files changed, 13 insertions(+), 29 deletions(-) diff --git a/fs/coda/cache.c b/fs/coda/cache.c index 5e526d018e232..e407c1b9212be 100644 --- a/fs/coda/cache.c +++ b/fs/coda/cache.c @@ -23,11 +23,14 @@ #include #include +static atomic_t permission_epoch = ATOMIC_INIT(0); + /* replace or extend an acl cache hit */ void coda_cache_enter(struct inode *inode, int mask) { struct coda_inode_info *cii = ITOC(inode); + cii->c_cached_epoch = atomic_read(&permission_epoch); if ( !coda_cred_ok(&cii->c_cached_cred) ) { coda_load_creds(&cii->c_cached_cred); cii->c_cached_perm = mask; @@ -42,22 +45,15 @@ void coda_cache_clear_inode(struct inode *inode) cii->c_cached_perm = 0; } -/* 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) +/* remove all acl caches */ +void coda_cache_clear_all(struct super_block *sb) { struct coda_sb_info *sbi; - struct coda_inode_info *cii; - struct list_head *tmp; sbi = coda_sbp(sb); if (!sbi) BUG(); - list_for_each(tmp, &sbi->sbi_cihead) - { - 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; - } + atomic_inc(&permission_epoch); } @@ -67,8 +63,9 @@ int coda_cache_check(struct inode *inode, int mask) struct coda_inode_info *cii = ITOC(inode); int hit; - hit = ((mask & cii->c_cached_perm) == mask) && - coda_cred_ok(&cii->c_cached_cred); + hit = (mask & cii->c_cached_perm) == mask && + coda_cred_ok(&cii->c_cached_cred) && + cii->c_cached_epoch == atomic_read(&permission_epoch); return hit; } diff --git a/fs/coda/cnode.c b/fs/coda/cnode.c index 95b5e49478f9b..384c715318b0e 100644 --- a/fs/coda/cnode.c +++ b/fs/coda/cnode.c @@ -64,7 +64,6 @@ struct inode * coda_iget(struct super_block * sb, ViceFid * fid, { struct inode *inode; struct coda_inode_info *cii; - struct coda_sb_info *sbi = coda_sbp(sb); unsigned long hash = coda_f2i(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, /* we still need to set i_ino for things like stat(2) */ inode->i_ino = hash; cii->c_mapcount = 0; - list_add(&cii->c_cilist, &sbi->sbi_cihead); unlock_new_inode(inode); } diff --git a/fs/coda/inode.c b/fs/coda/inode.c index 73739d68c5f53..1fb16b79dd0f4 100644 --- a/fs/coda/inode.c +++ b/fs/coda/inode.c @@ -46,7 +46,6 @@ static struct inode *coda_alloc_inode(struct super_block *sb) return NULL; memset(&ei->c_fid, 0, sizeof(struct ViceFid)); ei->c_flags = 0; - INIT_LIST_HEAD(&ei->c_cilist); memset(&ei->c_cached_cred, 0, sizeof(struct coda_cred)); ei->c_cached_perm = 0; return &ei->vfs_inode; @@ -170,7 +169,6 @@ static int coda_fill_super(struct super_block *sb, void *data, int silent) vc->vc_sb = sb; sbi->sbi_vcomm = vc; - INIT_LIST_HEAD(&sbi->sbi_cihead); sb->s_fs_info = sbi; sb->s_blocksize = 1024; /* XXXXX what do we put here?? */ @@ -217,7 +215,6 @@ static void coda_put_super(struct super_block *sb) sbi = coda_sbp(sb); sbi->sbi_vcomm->vc_sb = NULL; - list_del_init(&sbi->sbi_cihead); printk("Coda: Bye bye.\n"); kfree(sbi); @@ -225,9 +222,6 @@ static void coda_put_super(struct super_block *sb) 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); } diff --git a/fs/coda/upcall.c b/fs/coda/upcall.c index 6ab4f181513e7..308014e0f15bd 100644 --- a/fs/coda/upcall.c +++ b/fs/coda/upcall.c @@ -819,19 +819,14 @@ int coda_downcall(int opcode, union outputArgs * out, struct super_block *sb) switch (opcode) { case CODA_FLUSH : { - coda_cache_clear_all(sb, NULL); + coda_cache_clear_all(sb); shrink_dcache_sb(sb); coda_flag_inode(sb->s_root->d_inode, C_FLUSH); return(0); } case CODA_PURGEUSER : { - struct coda_cred *cred = &out->coda_purgeuser.cred; - if ( !cred ) { - printk("PURGEUSER: null cred!\n"); - return 0; - } - coda_cache_clear_all(sb, cred); + coda_cache_clear_all(sb); return(0); } diff --git a/include/linux/coda_cache.h b/include/linux/coda_cache.h index c5087185d378e..c910b5eb1ceb3 100644 --- a/include/linux/coda_cache.h +++ b/include/linux/coda_cache.h @@ -13,7 +13,7 @@ /* credential cache */ void coda_cache_enter(struct inode *inode, int mask); 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); /* for downcalls and attributes and lookups */ diff --git a/include/linux/coda_fs_i.h b/include/linux/coda_fs_i.h index e320452eba6ae..28511c79af455 100644 --- a/include/linux/coda_fs_i.h +++ b/include/linux/coda_fs_i.h @@ -21,6 +21,7 @@ struct coda_inode_info { u_short c_flags; /* flags (see below) */ struct list_head c_cilist; /* list of all coda inodes */ 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 */ unsigned int c_cached_perm; /* cached access permissions */ struct inode vfs_inode; diff --git a/include/linux/coda_psdev.h b/include/linux/coda_psdev.h index e8a5d2f18247d..74125fc4e0a8a 100644 --- a/include/linux/coda_psdev.h +++ b/include/linux/coda_psdev.h @@ -11,7 +11,6 @@ struct kstatfs; struct coda_sb_info { struct venus_comm *sbi_vcomm; - struct list_head sbi_cihead; }; /* communication pending/processing queues */ -- 2.53.0