Patch "afs: Fix incorrect triggering of sillyrename on 3rd-party invalidation" has been added to the 5.4-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    afs: Fix incorrect triggering of sillyrename on 3rd-party invalidation

to the 5.4-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     afs-fix-incorrect-triggering-of-sillyrename-on-3rd-p.patch
and it can be found in the queue-5.4 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit d20bc91bbd3cb9c49e5f16699fe65e5624f105b7
Author: David Howells <dhowells@xxxxxxxxxx>
Date:   Wed Sep 1 18:11:33 2021 +0100

    afs: Fix incorrect triggering of sillyrename on 3rd-party invalidation
    
    [ Upstream commit 63d49d843ef5fffeea069e0ffdfbd2bf40ba01c6 ]
    
    The AFS filesystem is currently triggering the silly-rename cleanup from
    afs_d_revalidate() when it sees that a dentry has been changed by a third
    party[1].  It should not be doing this as the cleanup includes deleting the
    silly-rename target file on iput.
    
    Fix this by removing the places in the d_revalidate handling that validate
    anything other than the directory and the dirent.  It probably should not
    be looking to validate the target inode of the dentry also.
    
    This includes removing the point in afs_d_revalidate() where the inode that
    a dentry used to point to was marked as being deleted (AFS_VNODE_DELETED).
    We don't know it got deleted.  It could have been renamed or it could have
    hard links remaining.
    
    This was reproduced by cloning a git repo onto an afs volume on one
    machine, switching to another machine and doing "git status", then
    switching back to the first and doing "git status".  The second status
    would show weird output due to ".git/index" getting deleted by the above
    mentioned mechanism.
    
    A simpler way to do it is to do:
    
            machine 1: touch a
            machine 2: touch b; mv -f b a
            machine 1: stat a
    
    on an afs volume.  The bug shows up as the stat failing with ENOENT and the
    file server log showing that machine 1 deleted "a".
    
    Fixes: 79ddbfa500b3 ("afs: Implement sillyrename for unlink and rename")
    Reported-by: Markus Suvanto <markus.suvanto@xxxxxxxxx>
    Signed-off-by: David Howells <dhowells@xxxxxxxxxx>
    Tested-by: Markus Suvanto <markus.suvanto@xxxxxxxxx>
    cc: linux-afs@xxxxxxxxxxxxxxxxxxx
    Link: https://bugzilla.kernel.org/show_bug.cgi?id=214217#c4 [1]
    Link: https://lore.kernel.org/r/163111668100.283156.3851669884664475428.stgit@xxxxxxxxxxxxxxxxxxxxxx/
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/fs/afs/dir.c b/fs/afs/dir.c
index e7494cd49ce7..8c39533d122a 100644
--- a/fs/afs/dir.c
+++ b/fs/afs/dir.c
@@ -977,9 +977,9 @@ static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry,
  */
 static int afs_d_revalidate_rcu(struct dentry *dentry)
 {
-	struct afs_vnode *dvnode, *vnode;
+	struct afs_vnode *dvnode;
 	struct dentry *parent;
-	struct inode *dir, *inode;
+	struct inode *dir;
 	long dir_version, de_version;
 
 	_enter("%p", dentry);
@@ -1009,18 +1009,6 @@ static int afs_d_revalidate_rcu(struct dentry *dentry)
 			return -ECHILD;
 	}
 
-	/* Check to see if the vnode referred to by the dentry still
-	 * has a callback.
-	 */
-	if (d_really_is_positive(dentry)) {
-		inode = d_inode_rcu(dentry);
-		if (inode) {
-			vnode = AFS_FS_I(inode);
-			if (!afs_check_validity(vnode))
-				return -ECHILD;
-		}
-	}
-
 	return 1; /* Still valid */
 }
 
@@ -1056,17 +1044,7 @@ static int afs_d_revalidate(struct dentry *dentry, unsigned int flags)
 	if (IS_ERR(key))
 		key = NULL;
 
-	if (d_really_is_positive(dentry)) {
-		inode = d_inode(dentry);
-		if (inode) {
-			vnode = AFS_FS_I(inode);
-			afs_validate(vnode, key);
-			if (test_bit(AFS_VNODE_DELETED, &vnode->flags))
-				goto out_bad;
-		}
-	}
-
-	/* lock down the parent dentry so we can peer at it */
+	/* Hold the parent dentry so we can peer at it */
 	parent = dget_parent(dentry);
 	dir = AFS_FS_I(d_inode(parent));
 
@@ -1075,7 +1053,7 @@ static int afs_d_revalidate(struct dentry *dentry, unsigned int flags)
 
 	if (test_bit(AFS_VNODE_DELETED, &dir->flags)) {
 		_debug("%pd: parent dir deleted", dentry);
-		goto out_bad_parent;
+		goto not_found;
 	}
 
 	/* We only need to invalidate a dentry if the server's copy changed
@@ -1101,12 +1079,12 @@ static int afs_d_revalidate(struct dentry *dentry, unsigned int flags)
 	case 0:
 		/* the filename maps to something */
 		if (d_really_is_negative(dentry))
-			goto out_bad_parent;
+			goto not_found;
 		inode = d_inode(dentry);
 		if (is_bad_inode(inode)) {
 			printk("kAFS: afs_d_revalidate: %pd2 has bad inode\n",
 			       dentry);
-			goto out_bad_parent;
+			goto not_found;
 		}
 
 		vnode = AFS_FS_I(inode);
@@ -1128,9 +1106,6 @@ static int afs_d_revalidate(struct dentry *dentry, unsigned int flags)
 			       dentry, fid.unique,
 			       vnode->fid.unique,
 			       vnode->vfs_inode.i_generation);
-			write_seqlock(&vnode->cb_lock);
-			set_bit(AFS_VNODE_DELETED, &vnode->flags);
-			write_sequnlock(&vnode->cb_lock);
 			goto not_found;
 		}
 		goto out_valid;
@@ -1145,7 +1120,7 @@ static int afs_d_revalidate(struct dentry *dentry, unsigned int flags)
 	default:
 		_debug("failed to iterate dir %pd: %d",
 		       parent, ret);
-		goto out_bad_parent;
+		goto not_found;
 	}
 
 out_valid:
@@ -1156,16 +1131,9 @@ static int afs_d_revalidate(struct dentry *dentry, unsigned int flags)
 	_leave(" = 1 [valid]");
 	return 1;
 
-	/* the dirent, if it exists, now points to a different vnode */
 not_found:
-	spin_lock(&dentry->d_lock);
-	dentry->d_flags |= DCACHE_NFSFS_RENAMED;
-	spin_unlock(&dentry->d_lock);
-
-out_bad_parent:
 	_debug("dropping dentry %pd2", dentry);
 	dput(parent);
-out_bad:
 	key_put(key);
 
 	_leave(" = 0 [bad]");



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux