]> git.karo-electronics.de Git - karo-tx-linux.git/blob - fs/orangefs/dcache.c
Merge remote-tracking branch 'kvm-arm/next'
[karo-tx-linux.git] / fs / orangefs / dcache.c
1 /*
2  * (C) 2001 Clemson University and The University of Chicago
3  *
4  * See COPYING in top-level directory.
5  */
6
7 /*
8  *  Implementation of dentry (directory cache) functions.
9  */
10
11 #include "protocol.h"
12 #include "pvfs2-kernel.h"
13
14 /* Returns 1 if dentry can still be trusted, else 0. */
15 static int pvfs2_revalidate_lookup(struct dentry *dentry)
16 {
17         struct dentry *parent_dentry = dget_parent(dentry);
18         struct inode *parent_inode = parent_dentry->d_inode;
19         struct pvfs2_inode_s *parent = PVFS2_I(parent_inode);
20         struct inode *inode = dentry->d_inode;
21         struct pvfs2_kernel_op_s *new_op;
22         int ret = 0;
23         int err = 0;
24
25         gossip_debug(GOSSIP_DCACHE_DEBUG, "%s: attempting lookup.\n", __func__);
26
27         new_op = op_alloc(PVFS2_VFS_OP_LOOKUP);
28         if (!new_op)
29                 goto out_put_parent;
30
31         new_op->upcall.req.lookup.sym_follow = PVFS2_LOOKUP_LINK_NO_FOLLOW;
32         new_op->upcall.req.lookup.parent_refn = parent->refn;
33         strncpy(new_op->upcall.req.lookup.d_name,
34                 dentry->d_name.name,
35                 PVFS2_NAME_LEN);
36
37         gossip_debug(GOSSIP_DCACHE_DEBUG,
38                      "%s:%s:%d interrupt flag [%d]\n",
39                      __FILE__,
40                      __func__,
41                      __LINE__,
42                      get_interruptible_flag(parent_inode));
43
44         err = service_operation(new_op, "pvfs2_lookup",
45                         get_interruptible_flag(parent_inode));
46         if (err)
47                 goto out_drop;
48
49         if (new_op->downcall.status != 0 ||
50             !match_handle(new_op->downcall.resp.lookup.refn.khandle, inode)) {
51                 gossip_debug(GOSSIP_DCACHE_DEBUG,
52                         "%s:%s:%d "
53                         "lookup failure |%s| or no match |%s|.\n",
54                         __FILE__,
55                         __func__,
56                         __LINE__,
57                         new_op->downcall.status ? "true" : "false",
58                         match_handle(new_op->downcall.resp.lookup.refn.khandle,
59                                         inode) ? "false" : "true");
60                 gossip_debug(GOSSIP_DCACHE_DEBUG,
61                              "%s:%s:%d revalidate failed\n",
62                              __FILE__, __func__, __LINE__);
63                 goto out_drop;
64         }
65
66         ret = 1;
67 out_release_op:
68         op_release(new_op);
69 out_put_parent:
70         dput(parent_dentry);
71         return ret;
72 out_drop:
73         d_drop(dentry);
74         goto out_release_op;
75 }
76
77 /*
78  * Verify that dentry is valid.
79  *
80  * Should return 1 if dentry can still be trusted, else 0
81  */
82 static int pvfs2_d_revalidate(struct dentry *dentry, unsigned int flags)
83 {
84         struct inode *inode;
85         int ret = 0;
86
87         if (flags & LOOKUP_RCU)
88                 return -ECHILD;
89
90         gossip_debug(GOSSIP_DCACHE_DEBUG, "%s: called on dentry %p.\n",
91                      __func__, dentry);
92
93         /* find inode from dentry */
94         if (!dentry->d_inode) {
95                 gossip_debug(GOSSIP_DCACHE_DEBUG, "%s: negative dentry.\n",
96                              __func__);
97                 goto invalid_exit;
98         }
99
100         gossip_debug(GOSSIP_DCACHE_DEBUG, "%s: inode valid.\n", __func__);
101         inode = dentry->d_inode;
102
103         /*
104          * first perform a lookup to make sure that the object not only
105          * exists, but is still in the expected place in the name space
106          */
107         if (!is_root_handle(inode)) {
108                 if (!pvfs2_revalidate_lookup(dentry))
109                         goto invalid_exit;
110         } else {
111                 gossip_debug(GOSSIP_DCACHE_DEBUG,
112                              "%s: root handle, lookup skipped.\n",
113                              __func__);
114         }
115
116         /* now perform getattr */
117         gossip_debug(GOSSIP_DCACHE_DEBUG,
118                      "%s: doing getattr: inode: %p, handle: %pU\n",
119                      __func__,
120                      inode,
121                      get_khandle_from_ino(inode));
122         ret = pvfs2_inode_getattr(inode, PVFS_ATTR_SYS_ALL_NOHINT);
123         gossip_debug(GOSSIP_DCACHE_DEBUG,
124                      "%s: getattr %s (ret = %d), returning %s for dentry i_count=%d\n",
125                      __func__,
126                      (ret == 0 ? "succeeded" : "failed"),
127                      ret,
128                      (ret == 0 ? "valid" : "INVALID"),
129                      atomic_read(&inode->i_count));
130         if (ret != 0)
131                 goto invalid_exit;
132
133         /* dentry is valid! */
134         return 1;
135
136 invalid_exit:
137         return 0;
138 }
139
140 const struct dentry_operations pvfs2_dentry_operations = {
141         .d_revalidate = pvfs2_d_revalidate,
142 };