aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSage Weil <sage@newdream.net>2011-07-26 14:30:43 -0400
committerSage Weil <sage@newdream.net>2011-07-26 14:30:43 -0400
commitbf1c6aca96c9d2f117dc7e590c2bc2304e7febe1 (patch)
tree1ecb6f35e572ba1e498390d1b09faf3c309bbaee
parent5f21c96dd5c615341963036ae8f5e4f5227a818d (diff)
ceph: protect d_parent access in ceph_d_revalidate
Protect d_parent with d_lock. Carry a reference. Simplify the flow so that there is a single exit point and cleanup. Reviewed-by: Yehuda Sadeh <yehuda@hq.newdream.net> Signed-off-by: Sage Weil <sage@newdream.net>
-rw-r--r--fs/ceph/dir.c32
1 files changed, 17 insertions, 15 deletions
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c
index ed296ec121d1..31d27f8f8261 100644
--- a/fs/ceph/dir.c
+++ b/fs/ceph/dir.c
@@ -1024,36 +1024,38 @@ static int dir_lease_is_valid(struct inode *dir, struct dentry *dentry)
1024 */ 1024 */
1025static int ceph_d_revalidate(struct dentry *dentry, struct nameidata *nd) 1025static int ceph_d_revalidate(struct dentry *dentry, struct nameidata *nd)
1026{ 1026{
1027 int valid = 0;
1027 struct inode *dir; 1028 struct inode *dir;
1028 1029
1029 if (nd && nd->flags & LOOKUP_RCU) 1030 if (nd && nd->flags & LOOKUP_RCU)
1030 return -ECHILD; 1031 return -ECHILD;
1031 1032
1032 dir = dentry->d_parent->d_inode;
1033
1034 dout("d_revalidate %p '%.*s' inode %p offset %lld\n", dentry, 1033 dout("d_revalidate %p '%.*s' inode %p offset %lld\n", dentry,
1035 dentry->d_name.len, dentry->d_name.name, dentry->d_inode, 1034 dentry->d_name.len, dentry->d_name.name, dentry->d_inode,
1036 ceph_dentry(dentry)->offset); 1035 ceph_dentry(dentry)->offset);
1037 1036
1037 dir = ceph_get_dentry_parent_inode(dentry);
1038
1038 /* always trust cached snapped dentries, snapdir dentry */ 1039 /* always trust cached snapped dentries, snapdir dentry */
1039 if (ceph_snap(dir) != CEPH_NOSNAP) { 1040 if (ceph_snap(dir) != CEPH_NOSNAP) {
1040 dout("d_revalidate %p '%.*s' inode %p is SNAPPED\n", dentry, 1041 dout("d_revalidate %p '%.*s' inode %p is SNAPPED\n", dentry,
1041 dentry->d_name.len, dentry->d_name.name, dentry->d_inode); 1042 dentry->d_name.len, dentry->d_name.name, dentry->d_inode);
1042 goto out_touch; 1043 valid = 1;
1044 } else if (dentry->d_inode &&
1045 ceph_snap(dentry->d_inode) == CEPH_SNAPDIR) {
1046 valid = 1;
1047 } else if (dentry_lease_is_valid(dentry) ||
1048 dir_lease_is_valid(dir, dentry)) {
1049 valid = 1;
1043 } 1050 }
1044 if (dentry->d_inode && ceph_snap(dentry->d_inode) == CEPH_SNAPDIR)
1045 goto out_touch;
1046 1051
1047 if (dentry_lease_is_valid(dentry) || 1052 dout("d_revalidate %p %s\n", dentry, valid ? "valid" : "invalid");
1048 dir_lease_is_valid(dir, dentry)) 1053 if (valid)
1049 goto out_touch; 1054 ceph_dentry_lru_touch(dentry);
1050 1055 else
1051 dout("d_revalidate %p invalid\n", dentry); 1056 d_drop(dentry);
1052 d_drop(dentry); 1057 iput(dir);
1053 return 0; 1058 return valid;
1054out_touch:
1055 ceph_dentry_lru_touch(dentry);
1056 return 1;
1057} 1059}
1058 1060
1059/* 1061/*