From: Greg Kroah-Hartman Date: Mon, 9 May 2022 14:42:31 +0000 (+0200) Subject: 4.19-stable patches X-Git-Tag: v4.9.313~48 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=c834378d4be75693f8e0217f404ff3d7e89010b7;p=thirdparty%2Fkernel%2Fstable-queue.git 4.19-stable patches added patches: btrfs-always-log-symlinks-in-full-mode.patch --- diff --git a/queue-4.19/btrfs-always-log-symlinks-in-full-mode.patch b/queue-4.19/btrfs-always-log-symlinks-in-full-mode.patch new file mode 100644 index 00000000000..47694226e1d --- /dev/null +++ b/queue-4.19/btrfs-always-log-symlinks-in-full-mode.patch @@ -0,0 +1,89 @@ +From d0e64a981fd841cb0f28fcd6afcac55e6f1e6994 Mon Sep 17 00:00:00 2001 +From: Filipe Manana +Date: Thu, 21 Apr 2022 10:56:39 +0100 +Subject: btrfs: always log symlinks in full mode + +From: Filipe Manana + +commit d0e64a981fd841cb0f28fcd6afcac55e6f1e6994 upstream. + +On Linux, empty symlinks are invalid, and attempting to create one with +the system call symlink(2) results in an -ENOENT error and this is +explicitly documented in the man page. + +If we rename a symlink that was created in the current transaction and its +parent directory was logged before, we actually end up logging the symlink +without logging its content, which is stored in an inline extent. That +means that after a power failure we can end up with an empty symlink, +having no content and an i_size of 0 bytes. + +It can be easily reproduced like this: + + $ mkfs.btrfs -f /dev/sdc + $ mount /dev/sdc /mnt + + $ mkdir /mnt/testdir + $ sync + + # Create a file inside the directory and fsync the directory. + $ touch /mnt/testdir/foo + $ xfs_io -c "fsync" /mnt/testdir + + # Create a symlink inside the directory and then rename the symlink. + $ ln -s /mnt/testdir/foo /mnt/testdir/bar + $ mv /mnt/testdir/bar /mnt/testdir/baz + + # Now fsync again the directory, this persist the log tree. + $ xfs_io -c "fsync" /mnt/testdir + + + + $ mount /dev/sdc /mnt + $ stat -c %s /mnt/testdir/baz + 0 + $ readlink /mnt/testdir/baz + $ + +Fix this by always logging symlinks in full mode (LOG_INODE_ALL), so that +their content is also logged. + +A test case for fstests will follow. + +CC: stable@vger.kernel.org # 4.9+ +Signed-off-by: Filipe Manana +Signed-off-by: David Sterba +Signed-off-by: Greg Kroah-Hartman +--- + fs/btrfs/tree-log.c | 14 +++++++++++++- + 1 file changed, 13 insertions(+), 1 deletion(-) + +--- a/fs/btrfs/tree-log.c ++++ b/fs/btrfs/tree-log.c +@@ -4907,6 +4907,18 @@ static int btrfs_log_inode(struct btrfs_ + } + + /* ++ * For symlinks, we must always log their content, which is stored in an ++ * inline extent, otherwise we could end up with an empty symlink after ++ * log replay, which is invalid on linux (symlink(2) returns -ENOENT if ++ * one attempts to create an empty symlink). ++ * We don't need to worry about flushing delalloc, because when we create ++ * the inline extent when the symlink is created (we never have delalloc ++ * for symlinks). ++ */ ++ if (S_ISLNK(inode->vfs_inode.i_mode)) ++ inode_only = LOG_INODE_ALL; ++ ++ /* + * a brute force approach to making sure we get the most uptodate + * copies of everything. + */ +@@ -5462,7 +5474,7 @@ process_leaf: + } + + ctx->log_new_dentries = false; +- if (type == BTRFS_FT_DIR || type == BTRFS_FT_SYMLINK) ++ if (type == BTRFS_FT_DIR) + log_mode = LOG_INODE_ALL; + ret = btrfs_log_inode(trans, root, BTRFS_I(di_inode), + log_mode, 0, LLONG_MAX, ctx); diff --git a/queue-4.19/series b/queue-4.19/series index 3a7a6d3b023..dcee50b4c1c 100644 --- a/queue-4.19/series +++ b/queue-4.19/series @@ -76,3 +76,4 @@ net-stmmac-dwmac-sun8i-add-missing-of_node_put-in-sun8i_dwmac_register_mdio_mux. net-emaclite-add-error-handling-for-of_address_to_resource.patch selftests-mirror_gre_bridge_1q-avoid-changing-pvid-while-interface-is-operational.patch smsc911x-allow-using-irq0.patch +btrfs-always-log-symlinks-in-full-mode.patch