From: Greg Kroah-Hartman Date: Thu, 18 Jun 2020 14:54:51 +0000 (+0200) Subject: 4.19-stable patches X-Git-Tag: v4.4.228~55 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=22d078da957a7656a27512ce5e9921da3919d6ac;p=thirdparty%2Fkernel%2Fstable-queue.git 4.19-stable patches added patches: btrfs-include-non-missing-as-a-qualifier-for-the-latest_bdev.patch btrfs-send-emit-file-capabilities-after-chown.patch --- diff --git a/queue-4.19/btrfs-include-non-missing-as-a-qualifier-for-the-latest_bdev.patch b/queue-4.19/btrfs-include-non-missing-as-a-qualifier-for-the-latest_bdev.patch new file mode 100644 index 00000000000..889e3868ee4 --- /dev/null +++ b/queue-4.19/btrfs-include-non-missing-as-a-qualifier-for-the-latest_bdev.patch @@ -0,0 +1,77 @@ +From 998a0671961f66e9fad4990ed75f80ba3088c2f1 Mon Sep 17 00:00:00 2001 +From: Anand Jain +Date: Tue, 5 May 2020 02:58:25 +0800 +Subject: btrfs: include non-missing as a qualifier for the latest_bdev + +From: Anand Jain + +commit 998a0671961f66e9fad4990ed75f80ba3088c2f1 upstream. + +btrfs_free_extra_devids() updates fs_devices::latest_bdev to point to +the bdev with greatest device::generation number. For a typical-missing +device the generation number is zero so fs_devices::latest_bdev will +never point to it. + +But if the missing device is due to alienation [1], then +device::generation is not zero and if it is greater or equal to the rest +of device generations in the list, then fs_devices::latest_bdev ends up +pointing to the missing device and reports the error like [2]. + +[1] We maintain devices of a fsid (as in fs_device::fsid) in the +fs_devices::devices list, a device is considered as an alien device +if its fsid does not match with the fs_device::fsid + +Consider a working filesystem with raid1: + + $ mkfs.btrfs -f -d raid1 -m raid1 /dev/sda /dev/sdb + $ mount /dev/sda /mnt-raid1 + $ umount /mnt-raid1 + +While mnt-raid1 was unmounted the user force-adds one of its devices to +another btrfs filesystem: + + $ mkfs.btrfs -f /dev/sdc + $ mount /dev/sdc /mnt-single + $ btrfs dev add -f /dev/sda /mnt-single + +Now the original mnt-raid1 fails to mount in degraded mode, because +fs_devices::latest_bdev is pointing to the alien device. + + $ mount -o degraded /dev/sdb /mnt-raid1 + +[2] +mount: wrong fs type, bad option, bad superblock on /dev/sdb, + missing codepage or helper program, or other error + + In some cases useful info is found in syslog - try + dmesg | tail or so. + + kernel: BTRFS warning (device sdb): devid 1 uuid 072a0192-675b-4d5a-8640-a5cf2b2c704d is missing + kernel: BTRFS error (device sdb): failed to read devices + kernel: BTRFS error (device sdb): open_ctree failed + +Fix the root cause by checking if the device is not missing before it +can be considered for the fs_devices::latest_bdev. + +CC: stable@vger.kernel.org # 4.19+ +Reviewed-by: Josef Bacik +Signed-off-by: Anand Jain +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/volumes.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/fs/btrfs/volumes.c ++++ b/fs/btrfs/volumes.c +@@ -951,6 +951,8 @@ again: + &device->dev_state)) { + if (!test_bit(BTRFS_DEV_STATE_REPLACE_TGT, + &device->dev_state) && ++ !test_bit(BTRFS_DEV_STATE_MISSING, ++ &device->dev_state) && + (!latest_dev || + device->generation > latest_dev->generation)) { + latest_dev = device; diff --git a/queue-4.19/btrfs-send-emit-file-capabilities-after-chown.patch b/queue-4.19/btrfs-send-emit-file-capabilities-after-chown.patch new file mode 100644 index 00000000000..4ab8d3453ae --- /dev/null +++ b/queue-4.19/btrfs-send-emit-file-capabilities-after-chown.patch @@ -0,0 +1,154 @@ +From 89efda52e6b6930f80f5adda9c3c9edfb1397191 Mon Sep 17 00:00:00 2001 +From: Marcos Paulo de Souza +Date: Sun, 10 May 2020 23:15:07 -0300 +Subject: btrfs: send: emit file capabilities after chown + +From: Marcos Paulo de Souza + +commit 89efda52e6b6930f80f5adda9c3c9edfb1397191 upstream. + +Whenever a chown is executed, all capabilities of the file being touched +are lost. When doing incremental send with a file with capabilities, +there is a situation where the capability can be lost on the receiving +side. The sequence of actions bellow shows the problem: + + $ mount /dev/sda fs1 + $ mount /dev/sdb fs2 + + $ touch fs1/foo.bar + $ setcap cap_sys_nice+ep fs1/foo.bar + $ btrfs subvolume snapshot -r fs1 fs1/snap_init + $ btrfs send fs1/snap_init | btrfs receive fs2 + + $ chgrp adm fs1/foo.bar + $ setcap cap_sys_nice+ep fs1/foo.bar + + $ btrfs subvolume snapshot -r fs1 fs1/snap_complete + $ btrfs subvolume snapshot -r fs1 fs1/snap_incremental + + $ btrfs send fs1/snap_complete | btrfs receive fs2 + $ btrfs send -p fs1/snap_init fs1/snap_incremental | btrfs receive fs2 + +At this point, only a chown was emitted by "btrfs send" since only the +group was changed. This makes the cap_sys_nice capability to be dropped +from fs2/snap_incremental/foo.bar + +To fix that, only emit capabilities after chown is emitted. The current +code first checks for xattrs that are new/changed, emits them, and later +emit the chown. Now, __process_new_xattr skips capabilities, letting +only finish_inode_if_needed to emit them, if they exist, for the inode +being processed. + +This behavior was being worked around in "btrfs receive" side by caching +the capability and only applying it after chown. Now, xattrs are only +emmited _after_ chown, making that workaround not needed anymore. + +Link: https://github.com/kdave/btrfs-progs/issues/202 +CC: stable@vger.kernel.org # 4.4+ +Suggested-by: Filipe Manana +Reviewed-by: Filipe Manana +Signed-off-by: Marcos Paulo de Souza +Signed-off-by: David Sterba +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/send.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 67 insertions(+) + +--- a/fs/btrfs/send.c ++++ b/fs/btrfs/send.c +@@ -23,6 +23,7 @@ + #include "btrfs_inode.h" + #include "transaction.h" + #include "compression.h" ++#include "xattr.h" + + /* + * Maximum number of references an extent can have in order for us to attempt to +@@ -4543,6 +4544,10 @@ static int __process_new_xattr(int num, + struct fs_path *p; + struct posix_acl_xattr_header dummy_acl; + ++ /* Capabilities are emitted by finish_inode_if_needed */ ++ if (!strncmp(name, XATTR_NAME_CAPS, name_len)) ++ return 0; ++ + p = fs_path_alloc(); + if (!p) + return -ENOMEM; +@@ -5105,6 +5110,64 @@ static int send_extent_data(struct send_ + return 0; + } + ++/* ++ * Search for a capability xattr related to sctx->cur_ino. If the capability is ++ * found, call send_set_xattr function to emit it. ++ * ++ * Return 0 if there isn't a capability, or when the capability was emitted ++ * successfully, or < 0 if an error occurred. ++ */ ++static int send_capabilities(struct send_ctx *sctx) ++{ ++ struct fs_path *fspath = NULL; ++ struct btrfs_path *path; ++ struct btrfs_dir_item *di; ++ struct extent_buffer *leaf; ++ unsigned long data_ptr; ++ char *buf = NULL; ++ int buf_len; ++ int ret = 0; ++ ++ path = alloc_path_for_send(); ++ if (!path) ++ return -ENOMEM; ++ ++ di = btrfs_lookup_xattr(NULL, sctx->send_root, path, sctx->cur_ino, ++ XATTR_NAME_CAPS, strlen(XATTR_NAME_CAPS), 0); ++ if (!di) { ++ /* There is no xattr for this inode */ ++ goto out; ++ } else if (IS_ERR(di)) { ++ ret = PTR_ERR(di); ++ goto out; ++ } ++ ++ leaf = path->nodes[0]; ++ buf_len = btrfs_dir_data_len(leaf, di); ++ ++ fspath = fs_path_alloc(); ++ buf = kmalloc(buf_len, GFP_KERNEL); ++ if (!fspath || !buf) { ++ ret = -ENOMEM; ++ goto out; ++ } ++ ++ ret = get_cur_path(sctx, sctx->cur_ino, sctx->cur_inode_gen, fspath); ++ if (ret < 0) ++ goto out; ++ ++ data_ptr = (unsigned long)(di + 1) + btrfs_dir_name_len(leaf, di); ++ read_extent_buffer(leaf, buf, data_ptr, buf_len); ++ ++ ret = send_set_xattr(sctx, fspath, XATTR_NAME_CAPS, ++ strlen(XATTR_NAME_CAPS), buf, buf_len); ++out: ++ kfree(buf); ++ fs_path_free(fspath); ++ btrfs_free_path(path); ++ return ret; ++} ++ + static int clone_range(struct send_ctx *sctx, + struct clone_root *clone_root, + const u64 disk_byte, +@@ -5936,6 +5999,10 @@ static int finish_inode_if_needed(struct + goto out; + } + ++ ret = send_capabilities(sctx); ++ if (ret < 0) ++ goto out; ++ + /* + * If other directory inodes depended on our current directory + * inode's move/rename, now do their move/rename operations. diff --git a/queue-4.19/series b/queue-4.19/series index 0af5a334f4e..6da0ff5c2b1 100644 --- a/queue-4.19/series +++ b/queue-4.19/series @@ -185,3 +185,5 @@ platform-x86-hp-wmi-convert-simple_strtoul-to-kstrto.patch platform-x86-intel-hid-add-a-quirk-to-support-hp-spe.patch platform-x86-intel-vbtn-only-blacklist-sw_tablet_mod.patch string.h-fix-incompatibility-between-fortify_source-.patch +btrfs-include-non-missing-as-a-qualifier-for-the-latest_bdev.patch +btrfs-send-emit-file-capabilities-after-chown.patch