]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.19-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 18 Jun 2020 14:54:51 +0000 (16:54 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 18 Jun 2020 14:54:51 +0000 (16:54 +0200)
added patches:
btrfs-include-non-missing-as-a-qualifier-for-the-latest_bdev.patch
btrfs-send-emit-file-capabilities-after-chown.patch

queue-4.19/btrfs-include-non-missing-as-a-qualifier-for-the-latest_bdev.patch [new file with mode: 0644]
queue-4.19/btrfs-send-emit-file-capabilities-after-chown.patch [new file with mode: 0644]
queue-4.19/series

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 (file)
index 0000000..889e386
--- /dev/null
@@ -0,0 +1,77 @@
+From 998a0671961f66e9fad4990ed75f80ba3088c2f1 Mon Sep 17 00:00:00 2001
+From: Anand Jain <anand.jain@oracle.com>
+Date: Tue, 5 May 2020 02:58:25 +0800
+Subject: btrfs: include non-missing as a qualifier for the latest_bdev
+
+From: Anand Jain <anand.jain@oracle.com>
+
+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 <josef@toxicpanda.com>
+Signed-off-by: Anand Jain <anand.jain@oracle.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..4ab8d34
--- /dev/null
@@ -0,0 +1,154 @@
+From 89efda52e6b6930f80f5adda9c3c9edfb1397191 Mon Sep 17 00:00:00 2001
+From: Marcos Paulo de Souza <mpdesouza@suse.com>
+Date: Sun, 10 May 2020 23:15:07 -0300
+Subject: btrfs: send: emit file capabilities after chown
+
+From: Marcos Paulo de Souza <mpdesouza@suse.com>
+
+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 <fdmanana@suse.com>
+Reviewed-by: Filipe Manana <fdmanana@suse.com>
+Signed-off-by: Marcos Paulo de Souza <mpdesouza@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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.
index 0af5a334f4eddef6ccbcd7f75407e43ac403969d..6da0ff5c2b1a9980f94ddf885c368db0781f7e6e 100644 (file)
@@ -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