Skip to content

Commit

Permalink
[PATCH] autofs4 needs to force fail return revalidate
Browse files Browse the repository at this point in the history
For a long time now I have had a problem with not being able to return a
lookup failure on an existsing directory.  In autofs this corresponds to a
mount failure on a autofs managed mount entry that is browsable (and so the
mount point directory exists).

While this problem has been present for a long time I've avoided resolving
it because it was not very visible.  But now that autofs v5 has "mount and
expire on demand" of nested multiple mounts, such as is found when mounting
an export list from a server, solving the problem cannot be avoided any
longer.

I've tried very hard to find a way to do this entirely within the autofs4
module but have not been able to find a satisfactory way to achieve it.

So, I need to propose a change to the VFS.

Signed-off-by: Ian Kent <raven@themaw.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
  • Loading branch information
Ian Kent authored and Linus Torvalds committed Sep 27, 2006
1 parent 1183dc9 commit bcdc5e0
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 23 deletions.
38 changes: 30 additions & 8 deletions fs/autofs4/root.c
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,9 @@ static int autofs4_dir_open(struct inode *inode, struct file *file)
nd.flags = LOOKUP_DIRECTORY;
ret = (dentry->d_op->d_revalidate)(dentry, &nd);

if (!ret) {
if (ret <= 0) {
if (ret < 0)
status = ret;
dcache_dir_close(inode, file);
goto out;
}
Expand Down Expand Up @@ -400,13 +402,23 @@ static int autofs4_revalidate(struct dentry *dentry, struct nameidata *nd)
struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb);
int oz_mode = autofs4_oz_mode(sbi);
int flags = nd ? nd->flags : 0;
int status = 0;
int status = 1;

/* Pending dentry */
if (autofs4_ispending(dentry)) {
if (!oz_mode)
status = try_to_fill_dentry(dentry, flags);
return !status;
/* The daemon never causes a mount to trigger */
if (oz_mode)
return 1;

/*
* A zero status is success otherwise we have a
* negative error code.
*/
status = try_to_fill_dentry(dentry, flags);
if (status == 0)
return 1;

return status;
}

/* Negative dentry.. invalidate if "old" */
Expand All @@ -421,9 +433,19 @@ static int autofs4_revalidate(struct dentry *dentry, struct nameidata *nd)
DPRINTK("dentry=%p %.*s, emptydir",
dentry, dentry->d_name.len, dentry->d_name.name);
spin_unlock(&dcache_lock);
if (!oz_mode)
status = try_to_fill_dentry(dentry, flags);
return !status;
/* The daemon never causes a mount to trigger */
if (oz_mode)
return 1;

/*
* A zero status is success otherwise we have a
* negative error code.
*/
status = try_to_fill_dentry(dentry, flags);
if (status == 0)
return 1;

return status;
}
spin_unlock(&dcache_lock);

Expand Down
50 changes: 35 additions & 15 deletions fs/namei.c
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,30 @@ void release_open_intent(struct nameidata *nd)
fput(nd->intent.open.file);
}

static inline struct dentry *
do_revalidate(struct dentry *dentry, struct nameidata *nd)
{
int status = dentry->d_op->d_revalidate(dentry, nd);
if (unlikely(status <= 0)) {
/*
* The dentry failed validation.
* If d_revalidate returned 0 attempt to invalidate
* the dentry otherwise d_revalidate is asking us
* to return a fail status.
*/
if (!status) {
if (!d_invalidate(dentry)) {
dput(dentry);
dentry = NULL;
}
} else {
dput(dentry);
dentry = ERR_PTR(status);
}
}
return dentry;
}

/*
* Internal lookup() using the new generic dcache.
* SMP-safe
Expand All @@ -386,12 +410,9 @@ static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name,
if (!dentry)
dentry = d_lookup(parent, name);

if (dentry && dentry->d_op && dentry->d_op->d_revalidate) {
if (!dentry->d_op->d_revalidate(dentry, nd) && !d_invalidate(dentry)) {
dput(dentry);
dentry = NULL;
}
}
if (dentry && dentry->d_op && dentry->d_op->d_revalidate)
dentry = do_revalidate(dentry, nd);

return dentry;
}

Expand Down Expand Up @@ -484,10 +505,9 @@ static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, s
*/
mutex_unlock(&dir->i_mutex);
if (result->d_op && result->d_op->d_revalidate) {
if (!result->d_op->d_revalidate(result, nd) && !d_invalidate(result)) {
dput(result);
result = do_revalidate(result, nd);
if (!result)
result = ERR_PTR(-ENOENT);
}
}
return result;
}
Expand Down Expand Up @@ -767,12 +787,12 @@ static int do_lookup(struct nameidata *nd, struct qstr *name,
goto done;

need_revalidate:
if (dentry->d_op->d_revalidate(dentry, nd))
goto done;
if (d_invalidate(dentry))
goto done;
dput(dentry);
goto need_lookup;
dentry = do_revalidate(dentry, nd);
if (!dentry)
goto need_lookup;
if (IS_ERR(dentry))
goto fail;
goto done;

fail:
return PTR_ERR(dentry);
Expand Down

0 comments on commit bcdc5e0

Please sign in to comment.