Commit e14720a1 authored by Trond Myklebust's avatar Trond Myklebust Committed by Linus Torvalds

[PATCH] Support dentry revalidation under open(".")

link_path_walk() currently treats the special filenames ".", ".."
and "/" differently in that it does not call down to the filesystem in
order to revalidate the cached dentry, but just assumes that it is
fine.

  For most filesystems this is OK, but it the case of the stateless
NFS, this means that it circumvents path staleness detection, and the
attribute+data cache revalidation code on such common commands as
opendir(".").

This change provides a way to do such revalidation for NFS without
impacting other filesystems. 

Note: the failure to revalidate the path here does not result in a
call to d_invalidate() unlike (all?) other calls to d_revalidate(). It
only results in an ESTALE error being returned to the caller.
parent 63360427
......@@ -572,7 +572,7 @@ int link_path_walk(const char * name, struct nameidata *nd)
while (*name=='/')
name++;
if (!*name)
goto return_base;
goto return_reval;
inode = nd->dentry->d_inode;
if (current->link_count)
......@@ -693,7 +693,7 @@ int link_path_walk(const char * name, struct nameidata *nd)
inode = nd->dentry->d_inode;
/* fallthrough */
case 1:
goto return_base;
goto return_reval;
}
if (nd->dentry->d_op && nd->dentry->d_op->d_hash) {
err = nd->dentry->d_op->d_hash(nd->dentry, &this);
......@@ -737,6 +737,20 @@ int link_path_walk(const char * name, struct nameidata *nd)
nd->last_type = LAST_DOT;
else if (this.len == 2 && this.name[1] == '.')
nd->last_type = LAST_DOTDOT;
else
goto return_base;
return_reval:
/*
* We bypassed the ordinary revalidation routines.
* We may need to check the cached dentry for staleness.
*/
if (nd->dentry && nd->dentry->d_sb &&
(nd->dentry->d_sb->s_type->fs_flags & FS_REVAL_DOT)) {
err = -ESTALE;
/* Note: we do not d_invalidate() */
if (!nd->dentry->d_op->d_revalidate(nd->dentry, nd))
break;
}
return_base:
return 0;
out_dput:
......
......@@ -1343,7 +1343,7 @@ static struct file_system_type nfs_fs_type = {
.name = "nfs",
.get_sb = nfs_get_sb,
.kill_sb = nfs_kill_super,
.fs_flags = FS_ODD_RENAME,
.fs_flags = FS_ODD_RENAME|FS_REVAL_DOT,
};
#ifdef CONFIG_NFS_V4
......@@ -1575,7 +1575,7 @@ static struct file_system_type nfs4_fs_type = {
.name = "nfs4",
.get_sb = nfs4_get_sb,
.kill_sb = nfs_kill_super,
.fs_flags = FS_ODD_RENAME,
.fs_flags = FS_ODD_RENAME|FS_REVAL_DOT,
};
#define nfs4_zero_state(nfsi) \
......
......@@ -89,6 +89,7 @@ extern int leases_enable, dir_notify_enable, lease_break_time;
/* public flags for file_system_type */
#define FS_REQUIRES_DEV 1
#define FS_REVAL_DOT 16384 /* Check the paths ".", ".." for staleness */
#define FS_ODD_RENAME 32768 /* Temporary stuff; will go away as soon
* as nfs_rename() will be cleaned up
*/
......
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