cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

dcache.c (3692B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * (C) 2001 Clemson University and The University of Chicago
      4 *
      5 * See COPYING in top-level directory.
      6 */
      7
      8/*
      9 *  Implementation of dentry (directory cache) functions.
     10 */
     11
     12#include "protocol.h"
     13#include "orangefs-kernel.h"
     14
     15/* Returns 1 if dentry can still be trusted, else 0. */
     16static int orangefs_revalidate_lookup(struct dentry *dentry)
     17{
     18	struct dentry *parent_dentry = dget_parent(dentry);
     19	struct inode *parent_inode = parent_dentry->d_inode;
     20	struct orangefs_inode_s *parent = ORANGEFS_I(parent_inode);
     21	struct inode *inode = dentry->d_inode;
     22	struct orangefs_kernel_op_s *new_op;
     23	int ret = 0;
     24	int err = 0;
     25
     26	gossip_debug(GOSSIP_DCACHE_DEBUG, "%s: attempting lookup.\n", __func__);
     27
     28	new_op = op_alloc(ORANGEFS_VFS_OP_LOOKUP);
     29	if (!new_op) {
     30		ret = -ENOMEM;
     31		goto out_put_parent;
     32	}
     33
     34	new_op->upcall.req.lookup.sym_follow = ORANGEFS_LOOKUP_LINK_NO_FOLLOW;
     35	new_op->upcall.req.lookup.parent_refn = parent->refn;
     36	strncpy(new_op->upcall.req.lookup.d_name,
     37		dentry->d_name.name,
     38		ORANGEFS_NAME_MAX - 1);
     39
     40	gossip_debug(GOSSIP_DCACHE_DEBUG,
     41		     "%s:%s:%d interrupt flag [%d]\n",
     42		     __FILE__,
     43		     __func__,
     44		     __LINE__,
     45		     get_interruptible_flag(parent_inode));
     46
     47	err = service_operation(new_op, "orangefs_lookup",
     48			get_interruptible_flag(parent_inode));
     49
     50	/* Positive dentry: reject if error or not the same inode. */
     51	if (inode) {
     52		if (err) {
     53			gossip_debug(GOSSIP_DCACHE_DEBUG,
     54			    "%s:%s:%d lookup failure.\n",
     55			    __FILE__, __func__, __LINE__);
     56			goto out_drop;
     57		}
     58		if (!match_handle(new_op->downcall.resp.lookup.refn.khandle,
     59		    inode)) {
     60			gossip_debug(GOSSIP_DCACHE_DEBUG,
     61			    "%s:%s:%d no match.\n",
     62			    __FILE__, __func__, __LINE__);
     63			goto out_drop;
     64		}
     65
     66	/* Negative dentry: reject if success or error other than ENOENT. */
     67	} else {
     68		gossip_debug(GOSSIP_DCACHE_DEBUG, "%s: negative dentry.\n",
     69		    __func__);
     70		if (!err || err != -ENOENT) {
     71			if (new_op->downcall.status != 0)
     72				gossip_debug(GOSSIP_DCACHE_DEBUG,
     73				    "%s:%s:%d lookup failure.\n",
     74				    __FILE__, __func__, __LINE__);
     75			goto out_drop;
     76		}
     77	}
     78
     79	orangefs_set_timeout(dentry);
     80	ret = 1;
     81out_release_op:
     82	op_release(new_op);
     83out_put_parent:
     84	dput(parent_dentry);
     85	return ret;
     86out_drop:
     87	gossip_debug(GOSSIP_DCACHE_DEBUG, "%s:%s:%d revalidate failed\n",
     88	    __FILE__, __func__, __LINE__);
     89	goto out_release_op;
     90}
     91
     92/*
     93 * Verify that dentry is valid.
     94 *
     95 * Should return 1 if dentry can still be trusted, else 0.
     96 */
     97static int orangefs_d_revalidate(struct dentry *dentry, unsigned int flags)
     98{
     99	int ret;
    100	unsigned long time = (unsigned long) dentry->d_fsdata;
    101
    102	if (time_before(jiffies, time))
    103		return 1;
    104
    105	if (flags & LOOKUP_RCU)
    106		return -ECHILD;
    107
    108	gossip_debug(GOSSIP_DCACHE_DEBUG, "%s: called on dentry %p.\n",
    109		     __func__, dentry);
    110
    111	/* skip root handle lookups. */
    112	if (dentry->d_inode && is_root_handle(dentry->d_inode))
    113		return 1;
    114
    115	/*
    116	 * If this passes, the positive dentry still exists or the negative
    117	 * dentry still does not exist.
    118	 */
    119	if (!orangefs_revalidate_lookup(dentry))
    120		return 0;
    121
    122	/* We do not need to continue with negative dentries. */
    123	if (!dentry->d_inode) {
    124		gossip_debug(GOSSIP_DCACHE_DEBUG,
    125		    "%s: negative dentry or positive dentry and inode valid.\n",
    126		    __func__);
    127		return 1;
    128	}
    129
    130	/* Now we must perform a getattr to validate the inode contents. */
    131
    132	ret = orangefs_inode_check_changed(dentry->d_inode);
    133	if (ret < 0) {
    134		gossip_debug(GOSSIP_DCACHE_DEBUG, "%s:%s:%d getattr failure.\n",
    135		    __FILE__, __func__, __LINE__);
    136		return 0;
    137	}
    138	return !ret;
    139}
    140
    141const struct dentry_operations orangefs_dentry_operations = {
    142	.d_revalidate = orangefs_d_revalidate,
    143};