Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Cache operations for Coda.
0004  * For Linux 2.1: (C) 1997 Carnegie Mellon University
0005  * For Linux 2.3: (C) 2000 Carnegie Mellon University
0006  *
0007  * Carnegie Mellon encourages users of this code to contribute improvements
0008  * to the Coda project http://www.coda.cs.cmu.edu/ <coda@cs.cmu.edu>.
0009  */
0010 
0011 #include <linux/types.h>
0012 #include <linux/kernel.h>
0013 #include <linux/time.h>
0014 #include <linux/fs.h>
0015 #include <linux/stat.h>
0016 #include <linux/errno.h>
0017 #include <linux/uaccess.h>
0018 #include <linux/string.h>
0019 #include <linux/list.h>
0020 #include <linux/sched.h>
0021 #include <linux/spinlock.h>
0022 
0023 #include <linux/coda.h>
0024 #include "coda_psdev.h"
0025 #include "coda_linux.h"
0026 #include "coda_cache.h"
0027 
0028 static atomic_t permission_epoch = ATOMIC_INIT(0);
0029 
0030 /* replace or extend an acl cache hit */
0031 void coda_cache_enter(struct inode *inode, int mask)
0032 {
0033     struct coda_inode_info *cii = ITOC(inode);
0034 
0035     spin_lock(&cii->c_lock);
0036     cii->c_cached_epoch = atomic_read(&permission_epoch);
0037     if (!uid_eq(cii->c_uid, current_fsuid())) {
0038         cii->c_uid = current_fsuid();
0039                 cii->c_cached_perm = mask;
0040         } else
0041                 cii->c_cached_perm |= mask;
0042     spin_unlock(&cii->c_lock);
0043 }
0044 
0045 /* remove cached acl from an inode */
0046 void coda_cache_clear_inode(struct inode *inode)
0047 {
0048     struct coda_inode_info *cii = ITOC(inode);
0049     spin_lock(&cii->c_lock);
0050     cii->c_cached_epoch = atomic_read(&permission_epoch) - 1;
0051     spin_unlock(&cii->c_lock);
0052 }
0053 
0054 /* remove all acl caches */
0055 void coda_cache_clear_all(struct super_block *sb)
0056 {
0057     atomic_inc(&permission_epoch);
0058 }
0059 
0060 
0061 /* check if the mask has been matched against the acl already */
0062 int coda_cache_check(struct inode *inode, int mask)
0063 {
0064     struct coda_inode_info *cii = ITOC(inode);
0065     int hit;
0066     
0067     spin_lock(&cii->c_lock);
0068     hit = (mask & cii->c_cached_perm) == mask &&
0069         uid_eq(cii->c_uid, current_fsuid()) &&
0070         cii->c_cached_epoch == atomic_read(&permission_epoch);
0071     spin_unlock(&cii->c_lock);
0072 
0073     return hit;
0074 }
0075 
0076 
0077 /* Purging dentries and children */
0078 /* The following routines drop dentries which are not
0079    in use and flag dentries which are in use to be 
0080    zapped later.
0081 
0082    The flags are detected by:
0083    - coda_dentry_revalidate (for lookups) if the flag is C_PURGE
0084    - coda_dentry_delete: to remove dentry from the cache when d_count
0085      falls to zero
0086    - an inode method coda_revalidate (for attributes) if the 
0087      flag is C_VATTR
0088 */
0089 
0090 /* this won't do any harm: just flag all children */
0091 static void coda_flag_children(struct dentry *parent, int flag)
0092 {
0093     struct dentry *de;
0094 
0095     spin_lock(&parent->d_lock);
0096     list_for_each_entry(de, &parent->d_subdirs, d_child) {
0097         /* don't know what to do with negative dentries */
0098         if (d_inode(de) ) 
0099             coda_flag_inode(d_inode(de), flag);
0100     }
0101     spin_unlock(&parent->d_lock);
0102     return; 
0103 }
0104 
0105 void coda_flag_inode_children(struct inode *inode, int flag)
0106 {
0107     struct dentry *alias_de;
0108 
0109     if ( !inode || !S_ISDIR(inode->i_mode)) 
0110         return; 
0111 
0112     alias_de = d_find_alias(inode);
0113     if (!alias_de)
0114         return;
0115     coda_flag_children(alias_de, flag);
0116     shrink_dcache_parent(alias_de);
0117     dput(alias_de);
0118 }
0119