xref: /openbmc/linux/fs/coda/cache.c (revision 0898782247ae533d1f4e47a06bc5d4870931b284)
1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds  * Cache operations for Coda.
41da177e4SLinus Torvalds  * For Linux 2.1: (C) 1997 Carnegie Mellon University
51da177e4SLinus Torvalds  * For Linux 2.3: (C) 2000 Carnegie Mellon University
61da177e4SLinus Torvalds  *
71da177e4SLinus Torvalds  * Carnegie Mellon encourages users of this code to contribute improvements
81da177e4SLinus Torvalds  * to the Coda project http://www.coda.cs.cmu.edu/ <coda@cs.cmu.edu>.
91da177e4SLinus Torvalds  */
101da177e4SLinus Torvalds 
111da177e4SLinus Torvalds #include <linux/types.h>
121da177e4SLinus Torvalds #include <linux/kernel.h>
131da177e4SLinus Torvalds #include <linux/time.h>
141da177e4SLinus Torvalds #include <linux/fs.h>
151da177e4SLinus Torvalds #include <linux/stat.h>
161da177e4SLinus Torvalds #include <linux/errno.h>
17834b46c3SFabian Frederick #include <linux/uaccess.h>
181da177e4SLinus Torvalds #include <linux/string.h>
191da177e4SLinus Torvalds #include <linux/list.h>
20e8edc6e0SAlexey Dobriyan #include <linux/sched.h>
21b5ce1d83SYoshihisa Abe #include <linux/spinlock.h>
221da177e4SLinus Torvalds 
231da177e4SLinus Torvalds #include <linux/coda.h>
24*8fc8b9dfSDavid Howells #include "coda_psdev.h"
2531a203dfSAl Viro #include "coda_linux.h"
2631a203dfSAl Viro #include "coda_cache.h"
271da177e4SLinus Torvalds 
281da177e4SLinus Torvalds static atomic_t permission_epoch = ATOMIC_INIT(0);
291da177e4SLinus Torvalds 
301da177e4SLinus Torvalds /* replace or extend an acl cache hit */
coda_cache_enter(struct inode * inode,int mask)311da177e4SLinus Torvalds void coda_cache_enter(struct inode *inode, int mask)
321da177e4SLinus Torvalds {
331da177e4SLinus Torvalds 	struct coda_inode_info *cii = ITOC(inode);
341da177e4SLinus Torvalds 
35b5ce1d83SYoshihisa Abe 	spin_lock(&cii->c_lock);
361da177e4SLinus Torvalds 	cii->c_cached_epoch = atomic_read(&permission_epoch);
3717499e33SEric W. Biederman 	if (!uid_eq(cii->c_uid, current_fsuid())) {
3897b7702cSDavid Howells 		cii->c_uid = current_fsuid();
391da177e4SLinus Torvalds                 cii->c_cached_perm = mask;
401da177e4SLinus Torvalds         } else
411da177e4SLinus Torvalds                 cii->c_cached_perm |= mask;
42b5ce1d83SYoshihisa Abe 	spin_unlock(&cii->c_lock);
431da177e4SLinus Torvalds }
441da177e4SLinus Torvalds 
451da177e4SLinus Torvalds /* remove cached acl from an inode */
coda_cache_clear_inode(struct inode * inode)461da177e4SLinus Torvalds void coda_cache_clear_inode(struct inode *inode)
471da177e4SLinus Torvalds {
481da177e4SLinus Torvalds 	struct coda_inode_info *cii = ITOC(inode);
49b5ce1d83SYoshihisa Abe 	spin_lock(&cii->c_lock);
5056ee3547SJan Harkes 	cii->c_cached_epoch = atomic_read(&permission_epoch) - 1;
51b5ce1d83SYoshihisa Abe 	spin_unlock(&cii->c_lock);
521da177e4SLinus Torvalds }
531da177e4SLinus Torvalds 
541da177e4SLinus Torvalds /* remove all acl caches */
coda_cache_clear_all(struct super_block * sb)551da177e4SLinus Torvalds void coda_cache_clear_all(struct super_block *sb)
561da177e4SLinus Torvalds {
571da177e4SLinus Torvalds 	atomic_inc(&permission_epoch);
581da177e4SLinus Torvalds }
591da177e4SLinus Torvalds 
601da177e4SLinus Torvalds 
611da177e4SLinus Torvalds /* check if the mask has been matched against the acl already */
coda_cache_check(struct inode * inode,int mask)621da177e4SLinus Torvalds int coda_cache_check(struct inode *inode, int mask)
631da177e4SLinus Torvalds {
641da177e4SLinus Torvalds 	struct coda_inode_info *cii = ITOC(inode);
651da177e4SLinus Torvalds 	int hit;
661da177e4SLinus Torvalds 
67b5ce1d83SYoshihisa Abe 	spin_lock(&cii->c_lock);
681da177e4SLinus Torvalds 	hit = (mask & cii->c_cached_perm) == mask &&
6917499e33SEric W. Biederman 	    uid_eq(cii->c_uid, current_fsuid()) &&
701da177e4SLinus Torvalds 	    cii->c_cached_epoch == atomic_read(&permission_epoch);
71b5ce1d83SYoshihisa Abe 	spin_unlock(&cii->c_lock);
721da177e4SLinus Torvalds 
731da177e4SLinus Torvalds 	return hit;
741da177e4SLinus Torvalds }
751da177e4SLinus Torvalds 
761da177e4SLinus Torvalds 
771da177e4SLinus Torvalds /* Purging dentries and children */
781da177e4SLinus Torvalds /* The following routines drop dentries which are not
791da177e4SLinus Torvalds    in use and flag dentries which are in use to be
801da177e4SLinus Torvalds    zapped later.
811da177e4SLinus Torvalds 
821da177e4SLinus Torvalds    The flags are detected by:
831da177e4SLinus Torvalds    - coda_dentry_revalidate (for lookups) if the flag is C_PURGE
841da177e4SLinus Torvalds    - coda_dentry_delete: to remove dentry from the cache when d_count
851da177e4SLinus Torvalds      falls to zero
861da177e4SLinus Torvalds    - an inode method coda_revalidate (for attributes) if the
871da177e4SLinus Torvalds      flag is C_VATTR
881da177e4SLinus Torvalds */
891da177e4SLinus Torvalds 
901da177e4SLinus Torvalds /* this won't do any harm: just flag all children */
coda_flag_children(struct dentry * parent,int flag)911da177e4SLinus Torvalds static void coda_flag_children(struct dentry *parent, int flag)
921da177e4SLinus Torvalds {
931da177e4SLinus Torvalds 	struct dentry *de;
941da177e4SLinus Torvalds 
952fd6b7f5SNick Piggin 	spin_lock(&parent->d_lock);
96946e51f2SAl Viro 	list_for_each_entry(de, &parent->d_subdirs, d_child) {
971da177e4SLinus Torvalds 		/* don't know what to do with negative dentries */
982b0143b5SDavid Howells 		if (d_inode(de) )
992b0143b5SDavid Howells 			coda_flag_inode(d_inode(de), flag);
1001da177e4SLinus Torvalds 	}
1012fd6b7f5SNick Piggin 	spin_unlock(&parent->d_lock);
1021da177e4SLinus Torvalds 	return;
1031da177e4SLinus Torvalds }
1041da177e4SLinus Torvalds 
coda_flag_inode_children(struct inode * inode,int flag)1051da177e4SLinus Torvalds void coda_flag_inode_children(struct inode *inode, int flag)
1061da177e4SLinus Torvalds {
1071da177e4SLinus Torvalds 	struct dentry *alias_de;
1081da177e4SLinus Torvalds 
1091da177e4SLinus Torvalds 	if ( !inode || !S_ISDIR(inode->i_mode))
1101da177e4SLinus Torvalds 		return;
1111da177e4SLinus Torvalds 
1121da177e4SLinus Torvalds 	alias_de = d_find_alias(inode);
1131da177e4SLinus Torvalds 	if (!alias_de)
1141da177e4SLinus Torvalds 		return;
1151da177e4SLinus Torvalds 	coda_flag_children(alias_de, flag);
1161da177e4SLinus Torvalds 	shrink_dcache_parent(alias_de);
1171da177e4SLinus Torvalds 	dput(alias_de);
1181da177e4SLinus Torvalds }
1191da177e4SLinus Torvalds 
120