From 7b0819a6ce863f543f5793b89e5aa343ca1890b9 Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Sun, 19 Jan 2020 22:18:35 -0500 Subject: [PATCH] fixes for 5.4 Signed-off-by: Sasha Levin --- ...ork-arguments-of-btrfs_unlink_subvol.patch | 151 ++++++++++++++++++ queue-5.4/series | 1 + 2 files changed, 152 insertions(+) create mode 100644 queue-5.4/btrfs-rework-arguments-of-btrfs_unlink_subvol.patch diff --git a/queue-5.4/btrfs-rework-arguments-of-btrfs_unlink_subvol.patch b/queue-5.4/btrfs-rework-arguments-of-btrfs_unlink_subvol.patch new file mode 100644 index 00000000000..b752268bc7f --- /dev/null +++ b/queue-5.4/btrfs-rework-arguments-of-btrfs_unlink_subvol.patch @@ -0,0 +1,151 @@ +From 3cf4bda4673838c6267b85f71721f4c91b30d1c4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 18 Dec 2019 17:20:27 -0500 +Subject: btrfs: rework arguments of btrfs_unlink_subvol + +From: Josef Bacik + +[ Upstream commit 045d3967b6920b663fc010ad414ade1b24143bd1 ] + +btrfs_unlink_subvol takes the name of the dentry and the root objectid +based on what kind of inode this is, either a real subvolume link or a +empty one that we inherited as a snapshot. We need to fix how we unlink +in the case for BTRFS_EMPTY_SUBVOL_DIR_OBJECTID in the future, so rework +btrfs_unlink_subvol to just take the dentry and handle getting the right +objectid given the type of inode this is. There is no functional change +here, simply pushing the work into btrfs_unlink_subvol() proper. + +Signed-off-by: Josef Bacik +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/inode.c | 46 ++++++++++++++++++++-------------------------- + 1 file changed, 20 insertions(+), 26 deletions(-) + +diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c +index 9e2a9b5449d9..6f0568fb5899 100644 +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -4215,18 +4215,30 @@ static int btrfs_unlink(struct inode *dir, struct dentry *dentry) + } + + static int btrfs_unlink_subvol(struct btrfs_trans_handle *trans, +- struct inode *dir, u64 objectid, +- const char *name, int name_len) ++ struct inode *dir, struct dentry *dentry) + { + struct btrfs_root *root = BTRFS_I(dir)->root; ++ struct btrfs_inode *inode = BTRFS_I(d_inode(dentry)); + struct btrfs_path *path; + struct extent_buffer *leaf; + struct btrfs_dir_item *di; + struct btrfs_key key; ++ const char *name = dentry->d_name.name; ++ int name_len = dentry->d_name.len; + u64 index; + int ret; ++ u64 objectid; + u64 dir_ino = btrfs_ino(BTRFS_I(dir)); + ++ if (btrfs_ino(inode) == BTRFS_FIRST_FREE_OBJECTID) { ++ objectid = inode->root->root_key.objectid; ++ } else if (btrfs_ino(inode) == BTRFS_EMPTY_SUBVOL_DIR_OBJECTID) { ++ objectid = inode->location.objectid; ++ } else { ++ WARN_ON(1); ++ return -EINVAL; ++ } ++ + path = btrfs_alloc_path(); + if (!path) + return -ENOMEM; +@@ -4475,8 +4487,7 @@ int btrfs_delete_subvolume(struct inode *dir, struct dentry *dentry) + + btrfs_record_snapshot_destroy(trans, BTRFS_I(dir)); + +- ret = btrfs_unlink_subvol(trans, dir, dest->root_key.objectid, +- dentry->d_name.name, dentry->d_name.len); ++ ret = btrfs_unlink_subvol(trans, dir, dentry); + if (ret) { + err = ret; + btrfs_abort_transaction(trans, ret); +@@ -4571,10 +4582,7 @@ static int btrfs_rmdir(struct inode *dir, struct dentry *dentry) + return PTR_ERR(trans); + + if (unlikely(btrfs_ino(BTRFS_I(inode)) == BTRFS_EMPTY_SUBVOL_DIR_OBJECTID)) { +- err = btrfs_unlink_subvol(trans, dir, +- BTRFS_I(inode)->location.objectid, +- dentry->d_name.name, +- dentry->d_name.len); ++ err = btrfs_unlink_subvol(trans, dir, dentry); + goto out; + } + +@@ -9530,7 +9538,6 @@ static int btrfs_rename_exchange(struct inode *old_dir, + u64 new_ino = btrfs_ino(BTRFS_I(new_inode)); + u64 old_idx = 0; + u64 new_idx = 0; +- u64 root_objectid; + int ret; + bool root_log_pinned = false; + bool dest_log_pinned = false; +@@ -9636,10 +9643,7 @@ static int btrfs_rename_exchange(struct inode *old_dir, + + /* src is a subvolume */ + if (old_ino == BTRFS_FIRST_FREE_OBJECTID) { +- root_objectid = BTRFS_I(old_inode)->root->root_key.objectid; +- ret = btrfs_unlink_subvol(trans, old_dir, root_objectid, +- old_dentry->d_name.name, +- old_dentry->d_name.len); ++ ret = btrfs_unlink_subvol(trans, old_dir, old_dentry); + } else { /* src is an inode */ + ret = __btrfs_unlink_inode(trans, root, BTRFS_I(old_dir), + BTRFS_I(old_dentry->d_inode), +@@ -9655,10 +9659,7 @@ static int btrfs_rename_exchange(struct inode *old_dir, + + /* dest is a subvolume */ + if (new_ino == BTRFS_FIRST_FREE_OBJECTID) { +- root_objectid = BTRFS_I(new_inode)->root->root_key.objectid; +- ret = btrfs_unlink_subvol(trans, new_dir, root_objectid, +- new_dentry->d_name.name, +- new_dentry->d_name.len); ++ ret = btrfs_unlink_subvol(trans, new_dir, new_dentry); + } else { /* dest is an inode */ + ret = __btrfs_unlink_inode(trans, dest, BTRFS_I(new_dir), + BTRFS_I(new_dentry->d_inode), +@@ -9856,7 +9857,6 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry, + struct inode *new_inode = d_inode(new_dentry); + struct inode *old_inode = d_inode(old_dentry); + u64 index = 0; +- u64 root_objectid; + int ret; + u64 old_ino = btrfs_ino(BTRFS_I(old_inode)); + bool log_pinned = false; +@@ -9964,10 +9964,7 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry, + BTRFS_I(old_inode), 1); + + if (unlikely(old_ino == BTRFS_FIRST_FREE_OBJECTID)) { +- root_objectid = BTRFS_I(old_inode)->root->root_key.objectid; +- ret = btrfs_unlink_subvol(trans, old_dir, root_objectid, +- old_dentry->d_name.name, +- old_dentry->d_name.len); ++ ret = btrfs_unlink_subvol(trans, old_dir, old_dentry); + } else { + ret = __btrfs_unlink_inode(trans, root, BTRFS_I(old_dir), + BTRFS_I(d_inode(old_dentry)), +@@ -9986,10 +9983,7 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry, + new_inode->i_ctime = current_time(new_inode); + if (unlikely(btrfs_ino(BTRFS_I(new_inode)) == + BTRFS_EMPTY_SUBVOL_DIR_OBJECTID)) { +- root_objectid = BTRFS_I(new_inode)->location.objectid; +- ret = btrfs_unlink_subvol(trans, new_dir, root_objectid, +- new_dentry->d_name.name, +- new_dentry->d_name.len); ++ ret = btrfs_unlink_subvol(trans, new_dir, new_dentry); + BUG_ON(new_inode->i_nlink == 0); + } else { + ret = btrfs_unlink_inode(trans, dest, BTRFS_I(new_dir), +-- +2.20.1 + diff --git a/queue-5.4/series b/queue-5.4/series index 182ce90da10..8edfd45ea00 100644 --- a/queue-5.4/series +++ b/queue-5.4/series @@ -80,6 +80,7 @@ mm-huge_memory.c-thp-fix-conflict-of-above-47bit-hint-address-and-pmd-alignment. mm-memcg-slab-fix-percpu-slab-vmstats-flushing.patch mm-memcg-slab-call-flush_memcg_workqueue-only-if-memcg-workqueue-is-valid.patch mm-debug_pagealloc-don-t-rely-on-static-keys-too-early.patch +btrfs-rework-arguments-of-btrfs_unlink_subvol.patch btrfs-fix-invalid-removal-of-root-ref.patch btrfs-do-not-delete-mismatched-root-refs.patch btrfs-relocation-fix-reloc_root-lifespan-and-access.patch -- 2.47.3