From: Greg Kroah-Hartman Date: Wed, 29 Aug 2018 17:28:45 +0000 (-0700) Subject: drop btrfs patch from 4.4 and 4.9 X-Git-Tag: v3.18.121~46 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=c77ac54ba08272c1dca7a265a1913ca4d4bca081;p=thirdparty%2Fkernel%2Fstable-queue.git drop btrfs patch from 4.4 and 4.9 --- diff --git a/queue-4.4/btrfs-fix-mount-failure-after-fsync-due-to-hard-link-recreation.patch b/queue-4.4/btrfs-fix-mount-failure-after-fsync-due-to-hard-link-recreation.patch deleted file mode 100644 index 0aa797cd3e1..00000000000 --- a/queue-4.4/btrfs-fix-mount-failure-after-fsync-due-to-hard-link-recreation.patch +++ /dev/null @@ -1,141 +0,0 @@ -From 0d836392cadd5535f4184d46d901a82eb276ed62 Mon Sep 17 00:00:00 2001 -From: Filipe Manana -Date: Fri, 20 Jul 2018 10:59:06 +0100 -Subject: Btrfs: fix mount failure after fsync due to hard link recreation - -From: Filipe Manana - -commit 0d836392cadd5535f4184d46d901a82eb276ed62 upstream. - -If we end up with logging an inode reference item which has the same name -but different index from the one we have persisted, we end up failing when -replaying the log with an errno value of -EEXIST. The error comes from -btrfs_add_link(), which is called from add_inode_ref(), when we are -replaying an inode reference item. - -Example scenario where this happens: - - $ mkfs.btrfs -f /dev/sdb - $ mount /dev/sdb /mnt - - $ touch /mnt/foo - $ ln /mnt/foo /mnt/bar - - $ sync - - # Rename the first hard link (foo) to a new name and rename the second - # hard link (bar) to the old name of the first hard link (foo). - $ mv /mnt/foo /mnt/qwerty - $ mv /mnt/bar /mnt/foo - - # Create a new file, in the same parent directory, with the old name of - # the second hard link (bar) and fsync this new file. - # We do this instead of calling fsync on foo/qwerty because if we did - # that the fsync resulted in a full transaction commit, not triggering - # the problem. - $ touch /mnt/bar - $ xfs_io -c "fsync" /mnt/bar - - - - $ mount /dev/sdb /mnt - mount: mount /dev/sdb on /mnt failed: File exists - -So fix this by checking if a conflicting inode reference exists (same -name, same parent but different index), removing it (and the associated -dir index entries from the parent inode) if it exists, before attempting -to add the new reference. - -A test case for fstests follows soon. - -CC: stable@vger.kernel.org # 4.4+ -Signed-off-by: Filipe Manana -Signed-off-by: David Sterba -Signed-off-by: Greg Kroah-Hartman - ---- - fs/btrfs/tree-log.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 66 insertions(+) - ---- a/fs/btrfs/tree-log.c -+++ b/fs/btrfs/tree-log.c -@@ -1188,6 +1188,46 @@ static int ref_get_fields(struct extent_ - return 0; - } - -+static int btrfs_inode_ref_exists(struct inode *inode, struct inode *dir, -+ const u8 ref_type, const char *name, -+ const int namelen) -+{ -+ struct btrfs_key key; -+ struct btrfs_path *path; -+ const u64 parent_id = btrfs_ino(BTRFS_I(dir)); -+ int ret; -+ -+ path = btrfs_alloc_path(); -+ if (!path) -+ return -ENOMEM; -+ -+ key.objectid = btrfs_ino(BTRFS_I(inode)); -+ key.type = ref_type; -+ if (key.type == BTRFS_INODE_REF_KEY) -+ key.offset = parent_id; -+ else -+ key.offset = btrfs_extref_hash(parent_id, name, namelen); -+ -+ ret = btrfs_search_slot(NULL, BTRFS_I(inode)->root, &key, path, 0, 0); -+ if (ret < 0) -+ goto out; -+ if (ret > 0) { -+ ret = 0; -+ goto out; -+ } -+ if (key.type == BTRFS_INODE_EXTREF_KEY) -+ ret = btrfs_find_name_in_ext_backref(path->nodes[0], -+ path->slots[0], parent_id, -+ name, namelen, NULL); -+ else -+ ret = btrfs_find_name_in_backref(path->nodes[0], path->slots[0], -+ name, namelen, NULL); -+ -+out: -+ btrfs_free_path(path); -+ return ret; -+} -+ - /* - * replay one inode back reference item found in the log tree. - * eb, slot and key refer to the buffer and key found in the log tree. -@@ -1295,6 +1335,32 @@ static noinline int add_inode_ref(struct - } - } - -+ /* -+ * If a reference item already exists for this inode -+ * with the same parent and name, but different index, -+ * drop it and the corresponding directory index entries -+ * from the parent before adding the new reference item -+ * and dir index entries, otherwise we would fail with -+ * -EEXIST returned from btrfs_add_link() below. -+ */ -+ ret = btrfs_inode_ref_exists(inode, dir, key->type, -+ name, namelen); -+ if (ret > 0) { -+ ret = btrfs_unlink_inode(trans, root, -+ BTRFS_I(dir), -+ BTRFS_I(inode), -+ name, namelen); -+ /* -+ * If we dropped the link count to 0, bump it so -+ * that later the iput() on the inode will not -+ * free it. We will fixup the link count later. -+ */ -+ if (!ret && inode->i_nlink == 0) -+ inc_nlink(inode); -+ } -+ if (ret < 0) -+ goto out; -+ - /* insert our name */ - ret = btrfs_add_link(trans, dir, inode, name, namelen, - 0, ref_index); diff --git a/queue-4.4/series b/queue-4.4/series index 87a7b2254b3..f7840ec4f09 100644 --- a/queue-4.4/series +++ b/queue-4.4/series @@ -44,4 +44,3 @@ smb3-do-not-send-smb3-set_info-if-nothing-changed.patch smb3-don-t-request-leases-in-symlink-creation-and-query.patch smb3-fill-in-statfs-fsid-and-correct-namelen.patch btrfs-don-t-leak-ret-from-do_chunk_alloc.patch -btrfs-fix-mount-failure-after-fsync-due-to-hard-link-recreation.patch diff --git a/queue-4.9/btrfs-fix-mount-failure-after-fsync-due-to-hard-link-recreation.patch b/queue-4.9/btrfs-fix-mount-failure-after-fsync-due-to-hard-link-recreation.patch deleted file mode 100644 index 40b70983a9c..00000000000 --- a/queue-4.9/btrfs-fix-mount-failure-after-fsync-due-to-hard-link-recreation.patch +++ /dev/null @@ -1,141 +0,0 @@ -From 0d836392cadd5535f4184d46d901a82eb276ed62 Mon Sep 17 00:00:00 2001 -From: Filipe Manana -Date: Fri, 20 Jul 2018 10:59:06 +0100 -Subject: Btrfs: fix mount failure after fsync due to hard link recreation - -From: Filipe Manana - -commit 0d836392cadd5535f4184d46d901a82eb276ed62 upstream. - -If we end up with logging an inode reference item which has the same name -but different index from the one we have persisted, we end up failing when -replaying the log with an errno value of -EEXIST. The error comes from -btrfs_add_link(), which is called from add_inode_ref(), when we are -replaying an inode reference item. - -Example scenario where this happens: - - $ mkfs.btrfs -f /dev/sdb - $ mount /dev/sdb /mnt - - $ touch /mnt/foo - $ ln /mnt/foo /mnt/bar - - $ sync - - # Rename the first hard link (foo) to a new name and rename the second - # hard link (bar) to the old name of the first hard link (foo). - $ mv /mnt/foo /mnt/qwerty - $ mv /mnt/bar /mnt/foo - - # Create a new file, in the same parent directory, with the old name of - # the second hard link (bar) and fsync this new file. - # We do this instead of calling fsync on foo/qwerty because if we did - # that the fsync resulted in a full transaction commit, not triggering - # the problem. - $ touch /mnt/bar - $ xfs_io -c "fsync" /mnt/bar - - - - $ mount /dev/sdb /mnt - mount: mount /dev/sdb on /mnt failed: File exists - -So fix this by checking if a conflicting inode reference exists (same -name, same parent but different index), removing it (and the associated -dir index entries from the parent inode) if it exists, before attempting -to add the new reference. - -A test case for fstests follows soon. - -CC: stable@vger.kernel.org # 4.4+ -Signed-off-by: Filipe Manana -Signed-off-by: David Sterba -Signed-off-by: Greg Kroah-Hartman - ---- - fs/btrfs/tree-log.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 66 insertions(+) - ---- a/fs/btrfs/tree-log.c -+++ b/fs/btrfs/tree-log.c -@@ -1206,6 +1206,46 @@ static int ref_get_fields(struct extent_ - return 0; - } - -+static int btrfs_inode_ref_exists(struct inode *inode, struct inode *dir, -+ const u8 ref_type, const char *name, -+ const int namelen) -+{ -+ struct btrfs_key key; -+ struct btrfs_path *path; -+ const u64 parent_id = btrfs_ino(BTRFS_I(dir)); -+ int ret; -+ -+ path = btrfs_alloc_path(); -+ if (!path) -+ return -ENOMEM; -+ -+ key.objectid = btrfs_ino(BTRFS_I(inode)); -+ key.type = ref_type; -+ if (key.type == BTRFS_INODE_REF_KEY) -+ key.offset = parent_id; -+ else -+ key.offset = btrfs_extref_hash(parent_id, name, namelen); -+ -+ ret = btrfs_search_slot(NULL, BTRFS_I(inode)->root, &key, path, 0, 0); -+ if (ret < 0) -+ goto out; -+ if (ret > 0) { -+ ret = 0; -+ goto out; -+ } -+ if (key.type == BTRFS_INODE_EXTREF_KEY) -+ ret = btrfs_find_name_in_ext_backref(path->nodes[0], -+ path->slots[0], parent_id, -+ name, namelen, NULL); -+ else -+ ret = btrfs_find_name_in_backref(path->nodes[0], path->slots[0], -+ name, namelen, NULL); -+ -+out: -+ btrfs_free_path(path); -+ return ret; -+} -+ - /* - * replay one inode back reference item found in the log tree. - * eb, slot and key refer to the buffer and key found in the log tree. -@@ -1313,6 +1353,32 @@ static noinline int add_inode_ref(struct - } - } - -+ /* -+ * If a reference item already exists for this inode -+ * with the same parent and name, but different index, -+ * drop it and the corresponding directory index entries -+ * from the parent before adding the new reference item -+ * and dir index entries, otherwise we would fail with -+ * -EEXIST returned from btrfs_add_link() below. -+ */ -+ ret = btrfs_inode_ref_exists(inode, dir, key->type, -+ name, namelen); -+ if (ret > 0) { -+ ret = btrfs_unlink_inode(trans, root, -+ BTRFS_I(dir), -+ BTRFS_I(inode), -+ name, namelen); -+ /* -+ * If we dropped the link count to 0, bump it so -+ * that later the iput() on the inode will not -+ * free it. We will fixup the link count later. -+ */ -+ if (!ret && inode->i_nlink == 0) -+ inc_nlink(inode); -+ } -+ if (ret < 0) -+ goto out; -+ - /* insert our name */ - ret = btrfs_add_link(trans, dir, inode, name, namelen, - 0, ref_index); diff --git a/queue-4.9/series b/queue-4.9/series index 9067e913099..e058f2180dd 100644 --- a/queue-4.9/series +++ b/queue-4.9/series @@ -56,4 +56,3 @@ smb3-do-not-send-smb3-set_info-if-nothing-changed.patch smb3-don-t-request-leases-in-symlink-creation-and-query.patch smb3-fill-in-statfs-fsid-and-correct-namelen.patch btrfs-don-t-leak-ret-from-do_chunk_alloc.patch -btrfs-fix-mount-failure-after-fsync-due-to-hard-link-recreation.patch