[PATCH][SRU][Disco] UBUNTU: SAUCE: shiftfs: fix buggy unlink logic

Christian Brauner christian.brauner at ubuntu.com
Thu Aug 29 18:45:07 UTC 2019


BugLink: https://bugs.launchpad.net/bugs/1841977

The way we messed with setting i_nlink was brittle and wrong. We used to
set the i_nlink of the shiftfs dentry to be deleted to the i_nlink count
of the underlay dentry of the directory it resided in which makes no
sense whatsoever. We also missed drop_nlink() which is crucial since
i_nlink affects whether a dentry is cleaned up on dput().
With this I cannot reproduce the bug anymore where shiftfs misleads zfs
into believing that a deleted file can not be removed from disk because
it is still referenced.

Fixes: commit 87011da41961 ("shiftfs: rework and extend")
Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 fs/shiftfs.c | 15 ++++++++++-----
 1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/fs/shiftfs.c b/fs/shiftfs.c
index 57e04a02d74c..084aa7a25566 100644
--- a/fs/shiftfs.c
+++ b/fs/shiftfs.c
@@ -585,6 +585,7 @@ static int shiftfs_rm(struct inode *dir, struct dentry *dentry, bool rmdir)
 {
 	struct dentry *lowerd = dentry->d_fsdata;
 	struct inode *loweri = dir->i_private;
+	struct inode *inode = d_inode(dentry);
 	int err;
 	const struct cred *oldcred;
 
@@ -594,15 +595,19 @@ static int shiftfs_rm(struct inode *dir, struct dentry *dentry, bool rmdir)
 		err = vfs_rmdir(loweri, lowerd);
 	else
 		err = vfs_unlink(loweri, lowerd, NULL);
-	inode_unlock(loweri);
 	revert_creds(oldcred);
 
-	shiftfs_copyattr(loweri, dir);
-	set_nlink(d_inode(dentry), loweri->i_nlink);
-	if (!err)
+	if (!err) {
 		d_drop(dentry);
 
-	set_nlink(dir, loweri->i_nlink);
+		if (rmdir)
+			clear_nlink(inode);
+		else
+			drop_nlink(inode);
+	}
+	inode_unlock(loweri);
+
+	shiftfs_copyattr(loweri, dir);
 
 	return err;
 }
-- 
2.23.0




More information about the kernel-team mailing list