| From b688741cb06695312f18b730653d6611e1bad28d Mon Sep 17 00:00:00 2001 |
| From: NeilBrown <neilb@suse.com> |
| Date: Fri, 25 Aug 2017 17:34:41 +1000 |
| Subject: NFS: revalidate "." etc correctly on "open". |
| |
| From: NeilBrown <neilb@suse.com> |
| |
| commit b688741cb06695312f18b730653d6611e1bad28d upstream. |
| |
| For correct close-to-open semantics, NFS must validate |
| the change attribute of a directory (or file) on open. |
| |
| Since commit ecf3d1f1aa74 ("vfs: kill FS_REVAL_DOT by adding a |
| d_weak_revalidate dentry op"), open() of "." or a path ending ".." is |
| not revalidated reliably (except when that direct is a mount point). |
| |
| Prior to that commit, "." was revalidated using nfs_lookup_revalidate() |
| which checks the LOOKUP_OPEN flag and forces revalidation if the flag is |
| set. |
| Since that commit, nfs_weak_revalidate() is used for NFSv3 (which |
| ignores the flags) and nothing is used for NFSv4. |
| |
| This is fixed by using nfs_lookup_verify_inode() in |
| nfs_weak_revalidate(). This does the revalidation exactly when needed. |
| Also, add a definition of .d_weak_revalidate for NFSv4. |
| |
| The incorrect behavior is easily demonstrated by running "echo *" in |
| some non-mountpoint NFS directory while watching network traffic. |
| Without this patch, "echo *" sometimes doesn't produce any traffic. |
| With the patch it always does. |
| |
| Fixes: ecf3d1f1aa74 ("vfs: kill FS_REVAL_DOT by adding a d_weak_revalidate dentry op") |
| cc: stable@vger.kernel.org (3.9+) |
| Signed-off-by: NeilBrown <neilb@suse.com> |
| Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| fs/nfs/dir.c | 3 ++- |
| 1 file changed, 2 insertions(+), 1 deletion(-) |
| |
| --- a/fs/nfs/dir.c |
| +++ b/fs/nfs/dir.c |
| @@ -1260,7 +1260,7 @@ static int nfs_weak_revalidate(struct de |
| return 0; |
| } |
| |
| - error = nfs_revalidate_inode(NFS_SERVER(inode), inode); |
| + error = nfs_lookup_verify_inode(inode, flags); |
| dfprintk(LOOKUPCACHE, "NFS: %s: inode %lu is %s\n", |
| __func__, inode->i_ino, error ? "invalid" : "valid"); |
| return !error; |
| @@ -1420,6 +1420,7 @@ static int nfs4_lookup_revalidate(struct |
| |
| const struct dentry_operations nfs4_dentry_operations = { |
| .d_revalidate = nfs4_lookup_revalidate, |
| + .d_weak_revalidate = nfs_weak_revalidate, |
| .d_delete = nfs_dentry_delete, |
| .d_iput = nfs_dentry_iput, |
| .d_automount = nfs_d_automount, |