Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * (C) 2001 Clemson University and The University of Chicago
0004  *
0005  * See COPYING in top-level directory.
0006  */
0007 
0008 /*
0009  *  Implementation of dentry (directory cache) functions.
0010  */
0011 
0012 #include "protocol.h"
0013 #include "orangefs-kernel.h"
0014 
0015 /* Returns 1 if dentry can still be trusted, else 0. */
0016 static int orangefs_revalidate_lookup(struct dentry *dentry)
0017 {
0018     struct dentry *parent_dentry = dget_parent(dentry);
0019     struct inode *parent_inode = parent_dentry->d_inode;
0020     struct orangefs_inode_s *parent = ORANGEFS_I(parent_inode);
0021     struct inode *inode = dentry->d_inode;
0022     struct orangefs_kernel_op_s *new_op;
0023     int ret = 0;
0024     int err = 0;
0025 
0026     gossip_debug(GOSSIP_DCACHE_DEBUG, "%s: attempting lookup.\n", __func__);
0027 
0028     new_op = op_alloc(ORANGEFS_VFS_OP_LOOKUP);
0029     if (!new_op) {
0030         ret = -ENOMEM;
0031         goto out_put_parent;
0032     }
0033 
0034     new_op->upcall.req.lookup.sym_follow = ORANGEFS_LOOKUP_LINK_NO_FOLLOW;
0035     new_op->upcall.req.lookup.parent_refn = parent->refn;
0036     strncpy(new_op->upcall.req.lookup.d_name,
0037         dentry->d_name.name,
0038         ORANGEFS_NAME_MAX - 1);
0039 
0040     gossip_debug(GOSSIP_DCACHE_DEBUG,
0041              "%s:%s:%d interrupt flag [%d]\n",
0042              __FILE__,
0043              __func__,
0044              __LINE__,
0045              get_interruptible_flag(parent_inode));
0046 
0047     err = service_operation(new_op, "orangefs_lookup",
0048             get_interruptible_flag(parent_inode));
0049 
0050     /* Positive dentry: reject if error or not the same inode. */
0051     if (inode) {
0052         if (err) {
0053             gossip_debug(GOSSIP_DCACHE_DEBUG,
0054                 "%s:%s:%d lookup failure.\n",
0055                 __FILE__, __func__, __LINE__);
0056             goto out_drop;
0057         }
0058         if (!match_handle(new_op->downcall.resp.lookup.refn.khandle,
0059             inode)) {
0060             gossip_debug(GOSSIP_DCACHE_DEBUG,
0061                 "%s:%s:%d no match.\n",
0062                 __FILE__, __func__, __LINE__);
0063             goto out_drop;
0064         }
0065 
0066     /* Negative dentry: reject if success or error other than ENOENT. */
0067     } else {
0068         gossip_debug(GOSSIP_DCACHE_DEBUG, "%s: negative dentry.\n",
0069             __func__);
0070         if (!err || err != -ENOENT) {
0071             if (new_op->downcall.status != 0)
0072                 gossip_debug(GOSSIP_DCACHE_DEBUG,
0073                     "%s:%s:%d lookup failure.\n",
0074                     __FILE__, __func__, __LINE__);
0075             goto out_drop;
0076         }
0077     }
0078 
0079     orangefs_set_timeout(dentry);
0080     ret = 1;
0081 out_release_op:
0082     op_release(new_op);
0083 out_put_parent:
0084     dput(parent_dentry);
0085     return ret;
0086 out_drop:
0087     gossip_debug(GOSSIP_DCACHE_DEBUG, "%s:%s:%d revalidate failed\n",
0088         __FILE__, __func__, __LINE__);
0089     goto out_release_op;
0090 }
0091 
0092 /*
0093  * Verify that dentry is valid.
0094  *
0095  * Should return 1 if dentry can still be trusted, else 0.
0096  */
0097 static int orangefs_d_revalidate(struct dentry *dentry, unsigned int flags)
0098 {
0099     int ret;
0100     unsigned long time = (unsigned long) dentry->d_fsdata;
0101 
0102     if (time_before(jiffies, time))
0103         return 1;
0104 
0105     if (flags & LOOKUP_RCU)
0106         return -ECHILD;
0107 
0108     gossip_debug(GOSSIP_DCACHE_DEBUG, "%s: called on dentry %p.\n",
0109              __func__, dentry);
0110 
0111     /* skip root handle lookups. */
0112     if (dentry->d_inode && is_root_handle(dentry->d_inode))
0113         return 1;
0114 
0115     /*
0116      * If this passes, the positive dentry still exists or the negative
0117      * dentry still does not exist.
0118      */
0119     if (!orangefs_revalidate_lookup(dentry))
0120         return 0;
0121 
0122     /* We do not need to continue with negative dentries. */
0123     if (!dentry->d_inode) {
0124         gossip_debug(GOSSIP_DCACHE_DEBUG,
0125             "%s: negative dentry or positive dentry and inode valid.\n",
0126             __func__);
0127         return 1;
0128     }
0129 
0130     /* Now we must perform a getattr to validate the inode contents. */
0131 
0132     ret = orangefs_inode_check_changed(dentry->d_inode);
0133     if (ret < 0) {
0134         gossip_debug(GOSSIP_DCACHE_DEBUG, "%s:%s:%d getattr failure.\n",
0135             __FILE__, __func__, __LINE__);
0136         return 0;
0137     }
0138     return !ret;
0139 }
0140 
0141 const struct dentry_operations orangefs_dentry_operations = {
0142     .d_revalidate = orangefs_d_revalidate,
0143 };