Merge branch 'vfs-scale-working' of git://git.kernel.org/pub/scm/linux/kernel/git/npiggin/linux-npiggin

* 'vfs-scale-working' of git://git.kernel.org/pub/scm/linux/kernel/git/npiggin/linux-npiggin:
  fs: fix do_last error case when need_reval_dot
  nfs: add missing rcu-walk check
  fs: hlist UP debug fixup
  fs: fix dropping of rcu-walk from force_reval_path
  fs: force_reval_path drop rcu-walk before d_invalidate
  fs: small rcu-walk documentation fixes

Fixed up trivial conflicts in Documentation/filesystems/porting
This commit is contained in:
Linus Torvalds
2011-01-13 20:14:13 -08:00
6 changed files with 40 additions and 14 deletions

View File

@@ -479,6 +479,14 @@ static int nameidata_dentry_drop_rcu(struct nameidata *nd, struct dentry *dentry
struct fs_struct *fs = current->fs;
struct dentry *parent = nd->path.dentry;
/*
* It can be possible to revalidate the dentry that we started
* the path walk with. force_reval_path may also revalidate the
* dentry already committed to the nameidata.
*/
if (unlikely(parent == dentry))
return nameidata_drop_rcu(nd);
BUG_ON(!(nd->flags & LOOKUP_RCU));
if (nd->root.mnt) {
spin_lock(&fs->lock);
@@ -583,6 +591,13 @@ void release_open_intent(struct nameidata *nd)
fput(nd->intent.open.file);
}
/*
* Call d_revalidate and handle filesystems that request rcu-walk
* to be dropped. This may be called and return in rcu-walk mode,
* regardless of success or error. If -ECHILD is returned, the caller
* must return -ECHILD back up the path walk stack so path walk may
* be restarted in ref-walk mode.
*/
static int d_revalidate(struct dentry *dentry, struct nameidata *nd)
{
int status;
@@ -673,6 +688,9 @@ force_reval_path(struct path *path, struct nameidata *nd)
return 0;
if (!status) {
/* Don't d_invalidate in rcu-walk mode */
if (nameidata_drop_rcu(nd))
return -ECHILD;
d_invalidate(dentry);
status = -ESTALE;
}
@@ -2105,11 +2123,13 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
dir = nd->path.dentry;
case LAST_DOT:
if (need_reval_dot(dir)) {
error = d_revalidate(nd->path.dentry, nd);
if (!error)
error = -ESTALE;
if (error < 0)
int status = d_revalidate(nd->path.dentry, nd);
if (!status)
status = -ESTALE;
if (status < 0) {
error = status;
goto exit;
}
}
/* fallthrough */
case LAST_ROOT: