Skip to content

Commit

Permalink
split do_revalidate() into RCU and non-RCU cases
Browse files Browse the repository at this point in the history
fixing oopsen in lookup_one_len()

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
  • Loading branch information
Al Viro committed Feb 15, 2011
1 parent 2464308 commit f5e1c1c
Showing 1 changed file with 30 additions and 17 deletions.
47 changes: 30 additions & 17 deletions fs/namei.c
Expand Up @@ -592,12 +592,10 @@ static int d_revalidate(struct dentry *dentry, struct nameidata *nd)
return status;
}

static inline struct dentry *
static struct dentry *
do_revalidate(struct dentry *dentry, struct nameidata *nd)
{
int status;

status = d_revalidate(dentry, nd);
int status = d_revalidate(dentry, nd);
if (unlikely(status <= 0)) {
/*
* The dentry failed validation.
Expand All @@ -606,24 +604,39 @@ do_revalidate(struct dentry *dentry, struct nameidata *nd)
* to return a fail status.
*/
if (status < 0) {
/* If we're in rcu-walk, we don't have a ref */
if (!(nd->flags & LOOKUP_RCU))
dput(dentry);
dput(dentry);
dentry = ERR_PTR(status);

} else {
/* Don't d_invalidate in rcu-walk mode */
if (nameidata_dentry_drop_rcu_maybe(nd, dentry))
return ERR_PTR(-ECHILD);
if (!d_invalidate(dentry)) {
dput(dentry);
dentry = NULL;
}
} else if (!d_invalidate(dentry)) {
dput(dentry);
dentry = NULL;
}
}
return dentry;
}

static inline struct dentry *
do_revalidate_rcu(struct dentry *dentry, struct nameidata *nd)
{
int status = dentry->d_op->d_revalidate(dentry, nd);
if (likely(status > 0))
return dentry;
if (status == -ECHILD) {
if (nameidata_dentry_drop_rcu(nd, dentry))
return ERR_PTR(-ECHILD);
return do_revalidate(dentry, nd);
}
if (status < 0)
return ERR_PTR(status);
/* Don't d_invalidate in rcu-walk mode */
if (nameidata_dentry_drop_rcu(nd, dentry))
return ERR_PTR(-ECHILD);
if (!d_invalidate(dentry)) {
dput(dentry);
dentry = NULL;
}
return dentry;
}

static inline int need_reval_dot(struct dentry *dentry)
{
if (likely(!(dentry->d_flags & DCACHE_OP_REVALIDATE)))
Expand Down Expand Up @@ -1260,7 +1273,7 @@ static int do_lookup(struct nameidata *nd, struct qstr *name,

nd->seq = seq;
if (unlikely(dentry->d_flags & DCACHE_OP_REVALIDATE)) {
dentry = do_revalidate(dentry, nd);
dentry = do_revalidate_rcu(dentry, nd);
if (!dentry)
goto need_lookup;
if (IS_ERR(dentry))
Expand Down

0 comments on commit f5e1c1c

Please sign in to comment.