--- /dev/null
+From d70cef0d46729808dc53f145372c02b145c92604 Mon Sep 17 00:00:00 2001
+From: Ira Weiny <ira.weiny@intel.com>
+Date: Wed, 27 Jan 2021 22:15:03 -0800
+Subject: btrfs: fix raid6 qstripe kmap
+
+From: Ira Weiny <ira.weiny@intel.com>
+
+commit d70cef0d46729808dc53f145372c02b145c92604 upstream.
+
+When a qstripe is required an extra page is allocated and mapped. There
+were 3 problems:
+
+1) There is no corresponding call of kunmap() for the qstripe page.
+2) There is no reason to map the qstripe page more than once if the
+ number of bits set in rbio->dbitmap is greater than one.
+3) There is no reason to map the parity page and unmap it each time
+ through the loop.
+
+The page memory can continue to be reused with a single mapping on each
+iteration by raid6_call.gen_syndrome() without remapping. So map the
+page for the duration of the loop.
+
+Similarly, improve the algorithm by mapping the parity page just 1 time.
+
+Fixes: 5a6ac9eacb49 ("Btrfs, raid56: support parity scrub on raid56")
+CC: stable@vger.kernel.org # 4.4.x: c17af96554a8: btrfs: raid56: simplify tracking of Q stripe presence
+CC: stable@vger.kernel.org # 4.4.x
+Signed-off-by: Ira Weiny <ira.weiny@intel.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/raid56.c | 21 ++++++++++-----------
+ 1 file changed, 10 insertions(+), 11 deletions(-)
+
+--- a/fs/btrfs/raid56.c
++++ b/fs/btrfs/raid56.c
+@@ -2375,16 +2375,21 @@ static noinline void finish_parity_scrub
+ SetPageUptodate(p_page);
+
+ if (has_qstripe) {
++ /* RAID6, allocate and map temp space for the Q stripe */
+ q_page = alloc_page(GFP_NOFS | __GFP_HIGHMEM);
+ if (!q_page) {
+ __free_page(p_page);
+ goto cleanup;
+ }
+ SetPageUptodate(q_page);
++ pointers[rbio->real_stripes - 1] = kmap(q_page);
+ }
+
+ atomic_set(&rbio->error, 0);
+
++ /* Map the parity stripe just once */
++ pointers[nr_data] = kmap(p_page);
++
+ for_each_set_bit(pagenr, rbio->dbitmap, rbio->stripe_npages) {
+ struct page *p;
+ void *parity;
+@@ -2394,16 +2399,8 @@ static noinline void finish_parity_scrub
+ pointers[stripe] = kmap(p);
+ }
+
+- /* then add the parity stripe */
+- pointers[stripe++] = kmap(p_page);
+-
+ if (has_qstripe) {
+- /*
+- * raid6, add the qstripe and call the
+- * library function to fill in our p/q
+- */
+- pointers[stripe++] = kmap(q_page);
+-
++ /* RAID6, call the library function to fill in our P/Q */
+ raid6_call.gen_syndrome(rbio->real_stripes, PAGE_SIZE,
+ pointers);
+ } else {
+@@ -2424,12 +2421,14 @@ static noinline void finish_parity_scrub
+
+ for (stripe = 0; stripe < nr_data; stripe++)
+ kunmap(page_in_rbio(rbio, stripe, pagenr, 0));
+- kunmap(p_page);
+ }
+
++ kunmap(p_page);
+ __free_page(p_page);
+- if (q_page)
++ if (q_page) {
++ kunmap(q_page);
+ __free_page(q_page);
++ }
+
+ writeback:
+ /*
--- /dev/null
+From 0f9c03d824f6f522d3bc43629635c9765546ebc5 Mon Sep 17 00:00:00 2001
+From: Nikolay Borisov <nborisov@suse.com>
+Date: Mon, 22 Feb 2021 18:40:42 +0200
+Subject: btrfs: free correct amount of space in btrfs_delayed_inode_reserve_metadata
+
+From: Nikolay Borisov <nborisov@suse.com>
+
+commit 0f9c03d824f6f522d3bc43629635c9765546ebc5 upstream.
+
+Following commit f218ea6c4792 ("btrfs: delayed-inode: Remove wrong
+qgroup meta reservation calls") this function now reserves num_bytes,
+rather than the fixed amount of nodesize. As such this requires the
+same amount to be freed in case of failure. Fix this by adjusting
+the amount we are freeing.
+
+Fixes: f218ea6c4792 ("btrfs: delayed-inode: Remove wrong qgroup meta reservation calls")
+CC: stable@vger.kernel.org # 4.19+
+Reviewed-by: Qu Wenruo <wqu@suse.com>
+Signed-off-by: Nikolay Borisov <nborisov@suse.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/delayed-inode.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/btrfs/delayed-inode.c
++++ b/fs/btrfs/delayed-inode.c
+@@ -642,7 +642,7 @@ static int btrfs_delayed_inode_reserve_m
+ btrfs_ino(inode),
+ num_bytes, 1);
+ } else {
+- btrfs_qgroup_free_meta_prealloc(root, fs_info->nodesize);
++ btrfs_qgroup_free_meta_prealloc(root, num_bytes);
+ }
+ return ret;
+ }
--- /dev/null
+From c17af96554a8a8777cbb0fd53b8497250e548b43 Mon Sep 17 00:00:00 2001
+From: David Sterba <dsterba@suse.com>
+Date: Wed, 19 Feb 2020 15:17:20 +0100
+Subject: btrfs: raid56: simplify tracking of Q stripe presence
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: David Sterba <dsterba@suse.com>
+
+commit c17af96554a8a8777cbb0fd53b8497250e548b43 upstream.
+
+There are temporary variables tracking the index of P and Q stripes, but
+none of them is really used as such, merely for determining if the Q
+stripe is present. This leads to compiler warnings with
+-Wunused-but-set-variable and has been reported several times.
+
+fs/btrfs/raid56.c: In function ‘finish_rmw’:
+fs/btrfs/raid56.c:1199:6: warning: variable ‘p_stripe’ set but not used [-Wunused-but-set-variable]
+ 1199 | int p_stripe = -1;
+ | ^~~~~~~~
+fs/btrfs/raid56.c: In function ‘finish_parity_scrub’:
+fs/btrfs/raid56.c:2356:6: warning: variable ‘p_stripe’ set but not used [-Wunused-but-set-variable]
+ 2356 | int p_stripe = -1;
+ | ^~~~~~~~
+
+Replace the two variables with one that has a clear meaning and also get
+rid of the warnings. The logic that verifies that there are only 2
+valid cases is unchanged.
+
+Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/btrfs/raid56.c | 37 +++++++++++++++----------------------
+ 1 file changed, 15 insertions(+), 22 deletions(-)
+
+--- a/fs/btrfs/raid56.c
++++ b/fs/btrfs/raid56.c
+@@ -1182,22 +1182,19 @@ static noinline void finish_rmw(struct b
+ int nr_data = rbio->nr_data;
+ int stripe;
+ int pagenr;
+- int p_stripe = -1;
+- int q_stripe = -1;
++ bool has_qstripe;
+ struct bio_list bio_list;
+ struct bio *bio;
+ int ret;
+
+ bio_list_init(&bio_list);
+
+- if (rbio->real_stripes - rbio->nr_data == 1) {
+- p_stripe = rbio->real_stripes - 1;
+- } else if (rbio->real_stripes - rbio->nr_data == 2) {
+- p_stripe = rbio->real_stripes - 2;
+- q_stripe = rbio->real_stripes - 1;
+- } else {
++ if (rbio->real_stripes - rbio->nr_data == 1)
++ has_qstripe = false;
++ else if (rbio->real_stripes - rbio->nr_data == 2)
++ has_qstripe = true;
++ else
+ BUG();
+- }
+
+ /* at this point we either have a full stripe,
+ * or we've read the full stripe from the drive.
+@@ -1241,7 +1238,7 @@ static noinline void finish_rmw(struct b
+ SetPageUptodate(p);
+ pointers[stripe++] = kmap(p);
+
+- if (q_stripe != -1) {
++ if (has_qstripe) {
+
+ /*
+ * raid6, add the qstripe and call the
+@@ -2340,8 +2337,7 @@ static noinline void finish_parity_scrub
+ int nr_data = rbio->nr_data;
+ int stripe;
+ int pagenr;
+- int p_stripe = -1;
+- int q_stripe = -1;
++ bool has_qstripe;
+ struct page *p_page = NULL;
+ struct page *q_page = NULL;
+ struct bio_list bio_list;
+@@ -2351,14 +2347,12 @@ static noinline void finish_parity_scrub
+
+ bio_list_init(&bio_list);
+
+- if (rbio->real_stripes - rbio->nr_data == 1) {
+- p_stripe = rbio->real_stripes - 1;
+- } else if (rbio->real_stripes - rbio->nr_data == 2) {
+- p_stripe = rbio->real_stripes - 2;
+- q_stripe = rbio->real_stripes - 1;
+- } else {
++ if (rbio->real_stripes - rbio->nr_data == 1)
++ has_qstripe = false;
++ else if (rbio->real_stripes - rbio->nr_data == 2)
++ has_qstripe = true;
++ else
+ BUG();
+- }
+
+ if (bbio->num_tgtdevs && bbio->tgtdev_map[rbio->scrubp]) {
+ is_replace = 1;
+@@ -2380,7 +2374,7 @@ static noinline void finish_parity_scrub
+ goto cleanup;
+ SetPageUptodate(p_page);
+
+- if (q_stripe != -1) {
++ if (has_qstripe) {
+ q_page = alloc_page(GFP_NOFS | __GFP_HIGHMEM);
+ if (!q_page) {
+ __free_page(p_page);
+@@ -2403,8 +2397,7 @@ static noinline void finish_parity_scrub
+ /* then add the parity stripe */
+ pointers[stripe++] = kmap(p_page);
+
+- if (q_stripe != -1) {
+-
++ if (has_qstripe) {
+ /*
+ * raid6, add the qstripe and call the
+ * library function to fill in our p/q
--- /dev/null
+From 4f6a49de64fd1b1dba5229c02047376da7cf24fd Mon Sep 17 00:00:00 2001
+From: Nikolay Borisov <nborisov@suse.com>
+Date: Tue, 23 Feb 2021 15:20:42 +0200
+Subject: btrfs: unlock extents in btrfs_zero_range in case of quota reservation errors
+
+From: Nikolay Borisov <nborisov@suse.com>
+
+commit 4f6a49de64fd1b1dba5229c02047376da7cf24fd upstream.
+
+If btrfs_qgroup_reserve_data returns an error (i.e quota limit reached)
+the handling logic directly goes to the 'out' label without first
+unlocking the extent range between lockstart, lockend. This results in
+deadlocks as other processes try to lock the same extent.
+
+Fixes: a7f8b1c2ac21 ("btrfs: file: reserve qgroup space after the hole punch range is locked")
+CC: stable@vger.kernel.org # 5.10+
+Reviewed-by: Qu Wenruo <wqu@suse.com>
+Signed-off-by: Nikolay Borisov <nborisov@suse.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/file.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+--- a/fs/btrfs/file.c
++++ b/fs/btrfs/file.c
+@@ -3016,8 +3016,11 @@ reserve_space:
+ goto out;
+ ret = btrfs_qgroup_reserve_data(inode, &data_reserved,
+ alloc_start, bytes_to_reserve);
+- if (ret)
++ if (ret) {
++ unlock_extent_cached(&BTRFS_I(inode)->io_tree, lockstart,
++ lockend, &cached_state);
+ goto out;
++ }
+ ret = btrfs_prealloc_file_range(inode, mode, alloc_start,
+ alloc_end - alloc_start,
+ i_blocksize(inode),
--- /dev/null
+From 5011c5a663b9c6d6aff3d394f11049b371199627 Mon Sep 17 00:00:00 2001
+From: Dan Carpenter <dancarpenter@oracle.com>
+Date: Wed, 17 Feb 2021 09:04:34 +0300
+Subject: btrfs: validate qgroup inherit for SNAP_CREATE_V2 ioctl
+
+From: Dan Carpenter <dancarpenter@oracle.com>
+
+commit 5011c5a663b9c6d6aff3d394f11049b371199627 upstream.
+
+The problem is we're copying "inherit" from user space but we don't
+necessarily know that we're copying enough data for a 64 byte
+struct. Then the next problem is that 'inherit' has a variable size
+array at the end, and we have to verify that array is the size we
+expected.
+
+Fixes: 6f72c7e20dba ("Btrfs: add qgroup inheritance")
+CC: stable@vger.kernel.org # 4.4+
+Signed-off-by: Dan Carpenter <dan.carpenter@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/ioctl.c | 19 ++++++++++++++++++-
+ 1 file changed, 18 insertions(+), 1 deletion(-)
+
+--- a/fs/btrfs/ioctl.c
++++ b/fs/btrfs/ioctl.c
+@@ -1842,7 +1842,10 @@ static noinline int btrfs_ioctl_snap_cre
+ if (vol_args->flags & BTRFS_SUBVOL_RDONLY)
+ readonly = true;
+ if (vol_args->flags & BTRFS_SUBVOL_QGROUP_INHERIT) {
+- if (vol_args->size > PAGE_SIZE) {
++ u64 nums;
++
++ if (vol_args->size < sizeof(*inherit) ||
++ vol_args->size > PAGE_SIZE) {
+ ret = -EINVAL;
+ goto free_args;
+ }
+@@ -1851,6 +1854,20 @@ static noinline int btrfs_ioctl_snap_cre
+ ret = PTR_ERR(inherit);
+ goto free_args;
+ }
++
++ if (inherit->num_qgroups > PAGE_SIZE ||
++ inherit->num_ref_copies > PAGE_SIZE ||
++ inherit->num_excl_copies > PAGE_SIZE) {
++ ret = -EINVAL;
++ goto free_inherit;
++ }
++
++ nums = inherit->num_qgroups + 2 * inherit->num_ref_copies +
++ 2 * inherit->num_excl_copies;
++ if (vol_args->size != struct_size(inherit, qgroups, nums)) {
++ ret = -EINVAL;
++ goto free_inherit;
++ }
+ }
+
+ ret = btrfs_ioctl_snap_create_transid(file, vol_args->name,
--- /dev/null
+From a14e5ec66a7a66e57b24e2469f9212a78460207e Mon Sep 17 00:00:00 2001
+From: Mikulas Patocka <mpatocka@redhat.com>
+Date: Tue, 23 Feb 2021 21:21:20 +0100
+Subject: dm bufio: subtract the number of initial sectors in dm_bufio_get_device_size
+
+From: Mikulas Patocka <mpatocka@redhat.com>
+
+commit a14e5ec66a7a66e57b24e2469f9212a78460207e upstream.
+
+dm_bufio_get_device_size returns the device size in blocks. Before
+returning the value, we must subtract the nubmer of starting
+sectors. The number of starting sectors may not be divisible by block
+size.
+
+Note that currently, no target is using dm_bufio_set_sector_offset and
+dm_bufio_get_device_size simultaneously, so this change has no effect.
+However, an upcoming dm-verity-fec fix needs this change.
+
+Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
+Reviewed-by: Milan Broz <gmazyland@gmail.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Mike Snitzer <snitzer@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/md/dm-bufio.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/drivers/md/dm-bufio.c
++++ b/drivers/md/dm-bufio.c
+@@ -1463,6 +1463,10 @@ EXPORT_SYMBOL_GPL(dm_bufio_get_block_siz
+ sector_t dm_bufio_get_device_size(struct dm_bufio_client *c)
+ {
+ sector_t s = i_size_read(c->bdev->bd_inode) >> SECTOR_SHIFT;
++ if (s >= c->start)
++ s -= c->start;
++ else
++ s = 0;
+ if (likely(c->sectors_per_block_bits >= 0))
+ s >>= c->sectors_per_block_bits;
+ else
--- /dev/null
+From 1aa46901ee51c1c5779b3b239ea0374a50c6d9ff Mon Sep 17 00:00:00 2001
+From: Kevin Wang <kevin1.wang@amd.com>
+Date: Tue, 2 Mar 2021 15:54:00 +0800
+Subject: drm/amdgpu: fix parameter error of RREG32_PCIE() in amdgpu_regs_pcie
+
+From: Kevin Wang <kevin1.wang@amd.com>
+
+commit 1aa46901ee51c1c5779b3b239ea0374a50c6d9ff upstream.
+
+the register offset isn't needed division by 4 to pass RREG32_PCIE()
+
+Signed-off-by: Kevin Wang <kevin1.wang@amd.com>
+Reviewed-by: Lijo Lazar <lijo.lazar@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
+@@ -239,7 +239,7 @@ static ssize_t amdgpu_debugfs_regs_pcie_
+ while (size) {
+ uint32_t value;
+
+- value = RREG32_PCIE(*pos >> 2);
++ value = RREG32_PCIE(*pos);
+ r = put_user(value, (uint32_t *)buf);
+ if (r)
+ return r;
+@@ -282,7 +282,7 @@ static ssize_t amdgpu_debugfs_regs_pcie_
+ if (r)
+ return r;
+
+- WREG32_PCIE(*pos >> 2, value);
++ WREG32_PCIE(*pos, value);
+
+ result += 4;
+ buf += 4;
--- /dev/null
+From 44cc89f764646b2f1f2ea5d1a08b230131707851 Mon Sep 17 00:00:00 2001
+From: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>
+Date: Thu, 25 Feb 2021 19:23:27 +0100
+Subject: PM: runtime: Update device status before letting suppliers suspend
+
+From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+
+commit 44cc89f764646b2f1f2ea5d1a08b230131707851 upstream.
+
+Because the PM-runtime status of the device is not updated in
+__rpm_callback(), attempts to suspend the suppliers of the given
+device triggered by rpm_put_suppliers() called by it may fail.
+
+Fix this by making __rpm_callback() update the device's status to
+RPM_SUSPENDED before calling rpm_put_suppliers() if the current
+status of the device is RPM_SUSPENDING and the callback just invoked
+by it has returned 0 (success).
+
+While at it, modify the code in __rpm_callback() to always check
+the device's PM-runtime status under its PM lock.
+
+Link: https://lore.kernel.org/linux-pm/CAPDyKFqm06KDw_p8WXsM4dijDbho4bb6T4k50UqqvR1_COsp8g@mail.gmail.com/
+Fixes: 21d5c57b3726 ("PM / runtime: Use device links")
+Reported-by: Elaine Zhang <zhangqing@rock-chips.com>
+Diagnosed-by: Ulf Hansson <ulf.hansson@linaro.org>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Tested-by: Elaine Zhang <zhangiqng@rock-chips.com>
+Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org>
+Cc: 4.10+ <stable@vger.kernel.org> # 4.10+
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/base/power/runtime.c | 62 +++++++++++++++++++++++++------------------
+ 1 file changed, 37 insertions(+), 25 deletions(-)
+
+--- a/drivers/base/power/runtime.c
++++ b/drivers/base/power/runtime.c
+@@ -304,22 +304,22 @@ static void rpm_put_suppliers(struct dev
+ static int __rpm_callback(int (*cb)(struct device *), struct device *dev)
+ __releases(&dev->power.lock) __acquires(&dev->power.lock)
+ {
+- int retval, idx;
+ bool use_links = dev->power.links_count > 0;
++ bool get = false;
++ int retval, idx;
++ bool put;
+
+ if (dev->power.irq_safe) {
+ spin_unlock(&dev->power.lock);
++ } else if (!use_links) {
++ spin_unlock_irq(&dev->power.lock);
+ } else {
++ get = dev->power.runtime_status == RPM_RESUMING;
++
+ spin_unlock_irq(&dev->power.lock);
+
+- /*
+- * Resume suppliers if necessary.
+- *
+- * The device's runtime PM status cannot change until this
+- * routine returns, so it is safe to read the status outside of
+- * the lock.
+- */
+- if (use_links && dev->power.runtime_status == RPM_RESUMING) {
++ /* Resume suppliers if necessary. */
++ if (get) {
+ idx = device_links_read_lock();
+
+ retval = rpm_get_suppliers(dev);
+@@ -334,24 +334,36 @@ static int __rpm_callback(int (*cb)(stru
+
+ if (dev->power.irq_safe) {
+ spin_lock(&dev->power.lock);
+- } else {
+- /*
+- * If the device is suspending and the callback has returned
+- * success, drop the usage counters of the suppliers that have
+- * been reference counted on its resume.
+- *
+- * Do that if resume fails too.
+- */
+- if (use_links
+- && ((dev->power.runtime_status == RPM_SUSPENDING && !retval)
+- || (dev->power.runtime_status == RPM_RESUMING && retval))) {
+- idx = device_links_read_lock();
++ return retval;
++ }
+
+- fail:
+- rpm_put_suppliers(dev);
++ spin_lock_irq(&dev->power.lock);
+
+- device_links_read_unlock(idx);
+- }
++ if (!use_links)
++ return retval;
++
++ /*
++ * If the device is suspending and the callback has returned success,
++ * drop the usage counters of the suppliers that have been reference
++ * counted on its resume.
++ *
++ * Do that if the resume fails too.
++ */
++ put = dev->power.runtime_status == RPM_SUSPENDING && !retval;
++ if (put)
++ __update_runtime_status(dev, RPM_SUSPENDED);
++ else
++ put = get && retval;
++
++ if (put) {
++ spin_unlock_irq(&dev->power.lock);
++
++ idx = device_links_read_lock();
++
++fail:
++ rpm_put_suppliers(dev);
++
++ device_links_read_unlock(idx);
+
+ spin_lock_irq(&dev->power.lock);
+ }