[SRU][FOCAL][PATCH 1/2] UBUNTU: SAUCE: Revert "UBUNTU: SAUCE: shiftfs: fix dentry revalidation"
Christian Brauner
christian.brauner at ubuntu.com
Tue Jun 23 17:46:15 UTC 2020
BugLink: https://bugs.launchpad.net/bugs/1884767
With patch cfaa482afb97 ("UBUNTU: SAUCE: shiftfs: fix dentry revalidation")
we tried to fix
https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1872757 but it
introduces a regression for shiftfs on btrfs users. Creating a btrfs
subvolume, deleting it, and then trying to recreate it will cause EEXIST
to be returned or the file be left in a half-created state. Faulty
behavior such as this can be reproduced via:
btrfs subvolume create my-subvol
ls -al my-subvol
btrfs subvolume delete my-subvol
We thus need to revert this change restoring the old behavior.This will
briefly resurface https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1872757
which is fixed in a follow-up patch on top of this revert. We simply
split out the minimal fix into a separate tiny patch.
This reverts commit cfaa482afb97e3c05d020af80b897b061109d51f.
Cc: Seth Forshee <seth.forshee at canonical.com>
Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
fs/shiftfs.c | 45 ++++++++++++++++++++++++++++++++-------------
1 file changed, 32 insertions(+), 13 deletions(-)
diff --git a/fs/shiftfs.c b/fs/shiftfs.c
index f5c709805fb8..5d88193b41db 100644
--- a/fs/shiftfs.c
+++ b/fs/shiftfs.c
@@ -240,17 +240,19 @@ static int shiftfs_d_weak_revalidate(struct dentry *dentry, unsigned int flags)
int err = 1;
struct dentry *lowerd = dentry->d_fsdata;
- if (lowerd->d_flags & DCACHE_OP_WEAK_REVALIDATE) {
+ if (d_is_negative(lowerd) != d_is_negative(dentry))
+ return 0;
+
+ if ((lowerd->d_flags & DCACHE_OP_WEAK_REVALIDATE))
err = lowerd->d_op->d_weak_revalidate(lowerd, flags);
- if (err < 0)
- return err;
- }
if (d_really_is_positive(dentry)) {
struct inode *inode = d_inode(dentry);
struct inode *loweri = d_inode(lowerd);
shiftfs_copyattr(loweri, inode);
+ if (!inode->i_nlink)
+ err = 0;
}
return err;
@@ -261,25 +263,23 @@ static int shiftfs_d_revalidate(struct dentry *dentry, unsigned int flags)
int err = 1;
struct dentry *lowerd = dentry->d_fsdata;
+ if (d_unhashed(lowerd) ||
+ ((d_is_negative(lowerd) != d_is_negative(dentry))))
+ return 0;
+
if (flags & LOOKUP_RCU)
return -ECHILD;
- if (lowerd->d_flags & DCACHE_OP_REVALIDATE) {
+ if ((lowerd->d_flags & DCACHE_OP_REVALIDATE))
err = lowerd->d_op->d_revalidate(lowerd, flags);
- if (err < 0)
- return err;
- if (!err) {
- if (!(flags & LOOKUP_RCU))
- d_invalidate(lowerd);
- return -ESTALE;
- }
- }
if (d_really_is_positive(dentry)) {
struct inode *inode = d_inode(dentry);
struct inode *loweri = d_inode(lowerd);
shiftfs_copyattr(loweri, inode);
+ if (!inode->i_nlink)
+ err = 0;
}
return err;
@@ -736,6 +736,24 @@ static int shiftfs_fiemap(struct inode *inode,
return err;
}
+static int shiftfs_tmpfile(struct inode *dir, struct dentry *dentry,
+ umode_t mode)
+{
+ int err;
+ const struct cred *oldcred;
+ struct dentry *lowerd = dentry->d_fsdata;
+ struct inode *loweri = dir->i_private;
+
+ if (!loweri->i_op->tmpfile)
+ return -EOPNOTSUPP;
+
+ oldcred = shiftfs_override_creds(dir->i_sb);
+ err = loweri->i_op->tmpfile(loweri, lowerd, mode);
+ revert_creds(oldcred);
+
+ return err;
+}
+
static int shiftfs_setattr(struct dentry *dentry, struct iattr *attr)
{
struct dentry *lowerd = dentry->d_fsdata;
@@ -1002,6 +1020,7 @@ static const struct inode_operations shiftfs_file_inode_operations = {
.listxattr = shiftfs_listxattr,
.permission = shiftfs_permission,
.setattr = shiftfs_setattr,
+ .tmpfile = shiftfs_tmpfile,
};
static const struct inode_operations shiftfs_special_inode_operations = {
base-commit: 51ee04d9d3b464e9aa8509013779491f0b001ebc
--
2.27.0
More information about the kernel-team
mailing list