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