Commit bf1c6aca authored by Sage Weil's avatar Sage Weil

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: default avatarYehuda Sadeh <yehuda@hq.newdream.net>
Signed-off-by: default avatarSage Weil <sage@newdream.net>
parent 5f21c96d
...@@ -1024,36 +1024,38 @@ static int dir_lease_is_valid(struct inode *dir, struct dentry *dentry) ...@@ -1024,36 +1024,38 @@ static int dir_lease_is_valid(struct inode *dir, struct dentry *dentry)
*/ */
static int ceph_d_revalidate(struct dentry *dentry, struct nameidata *nd) static int ceph_d_revalidate(struct dentry *dentry, struct nameidata *nd)
{ {
int valid = 0;
struct inode *dir; struct inode *dir;
if (nd && nd->flags & LOOKUP_RCU) if (nd && nd->flags & LOOKUP_RCU)
return -ECHILD; return -ECHILD;
dir = dentry->d_parent->d_inode;
dout("d_revalidate %p '%.*s' inode %p offset %lld\n", dentry, dout("d_revalidate %p '%.*s' inode %p offset %lld\n", dentry,
dentry->d_name.len, dentry->d_name.name, dentry->d_inode, dentry->d_name.len, dentry->d_name.name, dentry->d_inode,
ceph_dentry(dentry)->offset); ceph_dentry(dentry)->offset);
dir = ceph_get_dentry_parent_inode(dentry);
/* always trust cached snapped dentries, snapdir dentry */ /* always trust cached snapped dentries, snapdir dentry */
if (ceph_snap(dir) != CEPH_NOSNAP) { if (ceph_snap(dir) != CEPH_NOSNAP) {
dout("d_revalidate %p '%.*s' inode %p is SNAPPED\n", dentry, dout("d_revalidate %p '%.*s' inode %p is SNAPPED\n", dentry,
dentry->d_name.len, dentry->d_name.name, dentry->d_inode); dentry->d_name.len, dentry->d_name.name, dentry->d_inode);
goto out_touch; valid = 1;
} else if (dentry->d_inode &&
ceph_snap(dentry->d_inode) == CEPH_SNAPDIR) {
valid = 1;
} else if (dentry_lease_is_valid(dentry) ||
dir_lease_is_valid(dir, dentry)) {
valid = 1;
} }
if (dentry->d_inode && ceph_snap(dentry->d_inode) == CEPH_SNAPDIR)
goto out_touch;
if (dentry_lease_is_valid(dentry) || dout("d_revalidate %p %s\n", dentry, valid ? "valid" : "invalid");
dir_lease_is_valid(dir, dentry)) if (valid)
goto out_touch; ceph_dentry_lru_touch(dentry);
else
dout("d_revalidate %p invalid\n", dentry); d_drop(dentry);
d_drop(dentry); iput(dir);
return 0; return valid;
out_touch:
ceph_dentry_lru_touch(dentry);
return 1;
} }
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment