root/fs/orangefs/dcache.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. orangefs_revalidate_lookup
  2. orangefs_d_revalidate

   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. */
  16 static 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                 goto out_put_parent;
  31 
  32         new_op->upcall.req.lookup.sym_follow = ORANGEFS_LOOKUP_LINK_NO_FOLLOW;
  33         new_op->upcall.req.lookup.parent_refn = parent->refn;
  34         strncpy(new_op->upcall.req.lookup.d_name,
  35                 dentry->d_name.name,
  36                 ORANGEFS_NAME_MAX - 1);
  37 
  38         gossip_debug(GOSSIP_DCACHE_DEBUG,
  39                      "%s:%s:%d interrupt flag [%d]\n",
  40                      __FILE__,
  41                      __func__,
  42                      __LINE__,
  43                      get_interruptible_flag(parent_inode));
  44 
  45         err = service_operation(new_op, "orangefs_lookup",
  46                         get_interruptible_flag(parent_inode));
  47 
  48         /* Positive dentry: reject if error or not the same inode. */
  49         if (inode) {
  50                 if (err) {
  51                         gossip_debug(GOSSIP_DCACHE_DEBUG,
  52                             "%s:%s:%d lookup failure.\n",
  53                             __FILE__, __func__, __LINE__);
  54                         goto out_drop;
  55                 }
  56                 if (!match_handle(new_op->downcall.resp.lookup.refn.khandle,
  57                     inode)) {
  58                         gossip_debug(GOSSIP_DCACHE_DEBUG,
  59                             "%s:%s:%d no match.\n",
  60                             __FILE__, __func__, __LINE__);
  61                         goto out_drop;
  62                 }
  63 
  64         /* Negative dentry: reject if success or error other than ENOENT. */
  65         } else {
  66                 gossip_debug(GOSSIP_DCACHE_DEBUG, "%s: negative dentry.\n",
  67                     __func__);
  68                 if (!err || err != -ENOENT) {
  69                         if (new_op->downcall.status != 0)
  70                                 gossip_debug(GOSSIP_DCACHE_DEBUG,
  71                                     "%s:%s:%d lookup failure.\n",
  72                                     __FILE__, __func__, __LINE__);
  73                         goto out_drop;
  74                 }
  75         }
  76 
  77         orangefs_set_timeout(dentry);
  78         ret = 1;
  79 out_release_op:
  80         op_release(new_op);
  81 out_put_parent:
  82         dput(parent_dentry);
  83         return ret;
  84 out_drop:
  85         gossip_debug(GOSSIP_DCACHE_DEBUG, "%s:%s:%d revalidate failed\n",
  86             __FILE__, __func__, __LINE__);
  87         goto out_release_op;
  88 }
  89 
  90 /*
  91  * Verify that dentry is valid.
  92  *
  93  * Should return 1 if dentry can still be trusted, else 0.
  94  */
  95 static int orangefs_d_revalidate(struct dentry *dentry, unsigned int flags)
  96 {
  97         int ret;
  98         unsigned long time = (unsigned long) dentry->d_fsdata;
  99 
 100         if (time_before(jiffies, time))
 101                 return 1;
 102 
 103         if (flags & LOOKUP_RCU)
 104                 return -ECHILD;
 105 
 106         gossip_debug(GOSSIP_DCACHE_DEBUG, "%s: called on dentry %p.\n",
 107                      __func__, dentry);
 108 
 109         /* skip root handle lookups. */
 110         if (dentry->d_inode && is_root_handle(dentry->d_inode))
 111                 return 1;
 112 
 113         /*
 114          * If this passes, the positive dentry still exists or the negative
 115          * dentry still does not exist.
 116          */
 117         if (!orangefs_revalidate_lookup(dentry))
 118                 return 0;
 119 
 120         /* We do not need to continue with negative dentries. */
 121         if (!dentry->d_inode) {
 122                 gossip_debug(GOSSIP_DCACHE_DEBUG,
 123                     "%s: negative dentry or positive dentry and inode valid.\n",
 124                     __func__);
 125                 return 1;
 126         }
 127 
 128         /* Now we must perform a getattr to validate the inode contents. */
 129 
 130         ret = orangefs_inode_check_changed(dentry->d_inode);
 131         if (ret < 0) {
 132                 gossip_debug(GOSSIP_DCACHE_DEBUG, "%s:%s:%d getattr failure.\n",
 133                     __FILE__, __func__, __LINE__);
 134                 return 0;
 135         }
 136         return !ret;
 137 }
 138 
 139 const struct dentry_operations orangefs_dentry_operations = {
 140         .d_revalidate = orangefs_d_revalidate,
 141 };

/* [<][>][^][v][top][bottom][index][help] */