--- /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
+@@ -2390,16 +2390,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;
+@@ -2409,16 +2414,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 {
+@@ -2439,12 +2436,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 fd57a98d6f0c98fa295813087f13afb26c224e73 Mon Sep 17 00:00:00 2001
+From: Filipe Manana <fdmanana@suse.com>
+Date: Fri, 26 Feb 2021 17:51:44 +0000
+Subject: btrfs: fix warning when creating a directory with smack enabled
+
+From: Filipe Manana <fdmanana@suse.com>
+
+commit fd57a98d6f0c98fa295813087f13afb26c224e73 upstream.
+
+When we have smack enabled, during the creation of a directory smack may
+attempt to add a "smack transmute" xattr on the inode, which results in
+the following warning and trace:
+
+ WARNING: CPU: 3 PID: 2548 at fs/btrfs/transaction.c:537 start_transaction+0x489/0x4f0
+ Modules linked in: nft_objref nf_conntrack_netbios_ns (...)
+ CPU: 3 PID: 2548 Comm: mkdir Not tainted 5.9.0-rc2smack+ #81
+ Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.13.0-2.fc32 04/01/2014
+ RIP: 0010:start_transaction+0x489/0x4f0
+ Code: e9 be fc ff ff (...)
+ RSP: 0018:ffffc90001887d10 EFLAGS: 00010202
+ RAX: ffff88816f1e0000 RBX: 0000000000000201 RCX: 0000000000000003
+ RDX: 0000000000000201 RSI: 0000000000000002 RDI: ffff888177849000
+ RBP: ffff888177849000 R08: 0000000000000001 R09: 0000000000000004
+ R10: ffffffff825e8f7a R11: 0000000000000003 R12: ffffffffffffffe2
+ R13: 0000000000000000 R14: ffff88803d884270 R15: ffff8881680d8000
+ FS: 00007f67317b8440(0000) GS:ffff88817bcc0000(0000) knlGS:0000000000000000
+ CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+ CR2: 00007f67247a22a8 CR3: 000000004bfbc002 CR4: 0000000000370ee0
+ DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
+ DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
+ Call Trace:
+ ? slab_free_freelist_hook+0xea/0x1b0
+ ? trace_hardirqs_on+0x1c/0xe0
+ btrfs_setxattr_trans+0x3c/0xf0
+ __vfs_setxattr+0x63/0x80
+ smack_d_instantiate+0x2d3/0x360
+ security_d_instantiate+0x29/0x40
+ d_instantiate_new+0x38/0x90
+ btrfs_mkdir+0x1cf/0x1e0
+ vfs_mkdir+0x14f/0x200
+ do_mkdirat+0x6d/0x110
+ do_syscall_64+0x2d/0x40
+ entry_SYSCALL_64_after_hwframe+0x44/0xa9
+ RIP: 0033:0x7f673196ae6b
+ Code: 8b 05 11 (...)
+ RSP: 002b:00007ffc3c679b18 EFLAGS: 00000246 ORIG_RAX: 0000000000000053
+ RAX: ffffffffffffffda RBX: 00000000000001ff RCX: 00007f673196ae6b
+ RDX: 0000000000000000 RSI: 00000000000001ff RDI: 00007ffc3c67a30d
+ RBP: 00007ffc3c67a30d R08: 00000000000001ff R09: 0000000000000000
+ R10: 000055d3e39fe930 R11: 0000000000000246 R12: 0000000000000000
+ R13: 00007ffc3c679cd8 R14: 00007ffc3c67a30d R15: 00007ffc3c679ce0
+ irq event stamp: 11029
+ hardirqs last enabled at (11037): [<ffffffff81153fe6>] console_unlock+0x486/0x670
+ hardirqs last disabled at (11044): [<ffffffff81153c01>] console_unlock+0xa1/0x670
+ softirqs last enabled at (8864): [<ffffffff81e0102f>] asm_call_on_stack+0xf/0x20
+ softirqs last disabled at (8851): [<ffffffff81e0102f>] asm_call_on_stack+0xf/0x20
+
+This happens because at btrfs_mkdir() we call d_instantiate_new() while
+holding a transaction handle, which results in the following call chain:
+
+ btrfs_mkdir()
+ trans = btrfs_start_transaction(root, 5);
+
+ d_instantiate_new()
+ smack_d_instantiate()
+ __vfs_setxattr()
+ btrfs_setxattr_trans()
+ btrfs_start_transaction()
+ start_transaction()
+ WARN_ON()
+ --> a tansaction start has TRANS_EXTWRITERS
+ set in its type
+ h->orig_rsv = h->block_rsv
+ h->block_rsv = NULL
+
+ btrfs_end_transaction(trans)
+
+Besides the warning triggered at start_transaction, we set the handle's
+block_rsv to NULL which may cause some surprises later on.
+
+So fix this by making btrfs_setxattr_trans() not start a transaction when
+we already have a handle on one, stored in current->journal_info, and use
+that handle. We are good to use the handle because at btrfs_mkdir() we did
+reserve space for the xattr and the inode item.
+
+Reported-by: Casey Schaufler <casey@schaufler-ca.com>
+CC: stable@vger.kernel.org # 5.4+
+Acked-by: Casey Schaufler <casey@schaufler-ca.com>
+Tested-by: Casey Schaufler <casey@schaufler-ca.com>
+Link: https://lore.kernel.org/linux-btrfs/434d856f-bd7b-4889-a6ec-e81aaebfa735@schaufler-ca.com/
+Signed-off-by: Filipe Manana <fdmanana@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/btrfs/xattr.c | 31 +++++++++++++++++++++++++++----
+ 1 file changed, 27 insertions(+), 4 deletions(-)
+
+--- a/fs/btrfs/xattr.c
++++ b/fs/btrfs/xattr.c
+@@ -227,11 +227,33 @@ int btrfs_setxattr_trans(struct inode *i
+ {
+ struct btrfs_root *root = BTRFS_I(inode)->root;
+ struct btrfs_trans_handle *trans;
++ const bool start_trans = (current->journal_info == NULL);
+ int ret;
+
+- trans = btrfs_start_transaction(root, 2);
+- if (IS_ERR(trans))
+- return PTR_ERR(trans);
++ if (start_trans) {
++ /*
++ * 1 unit for inserting/updating/deleting the xattr
++ * 1 unit for the inode item update
++ */
++ trans = btrfs_start_transaction(root, 2);
++ if (IS_ERR(trans))
++ return PTR_ERR(trans);
++ } else {
++ /*
++ * This can happen when smack is enabled and a directory is being
++ * created. It happens through d_instantiate_new(), which calls
++ * smack_d_instantiate(), which in turn calls __vfs_setxattr() to
++ * set the transmute xattr (XATTR_NAME_SMACKTRANSMUTE) on the
++ * inode. We have already reserved space for the xattr and inode
++ * update at btrfs_mkdir(), so just use the transaction handle.
++ * We don't join or start a transaction, as that will reset the
++ * block_rsv of the handle and trigger a warning for the start
++ * case.
++ */
++ ASSERT(strncmp(name, XATTR_SECURITY_PREFIX,
++ XATTR_SECURITY_PREFIX_LEN) == 0);
++ trans = current->journal_info;
++ }
+
+ ret = btrfs_setxattr(trans, inode, name, value, size, flags);
+ if (ret)
+@@ -242,7 +264,8 @@ int btrfs_setxattr_trans(struct inode *i
+ ret = btrfs_update_inode(trans, root, inode);
+ BUG_ON(ret);
+ out:
+- btrfs_end_transaction(trans);
++ if (start_trans)
++ btrfs_end_transaction(trans);
+ return ret;
+ }
+
--- /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
+@@ -649,7 +649,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
+@@ -1198,22 +1198,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.
+@@ -1257,7 +1254,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
+@@ -2355,8 +2352,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;
+@@ -2366,14 +2362,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;
+@@ -2395,7 +2389,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);
+@@ -2418,8 +2412,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
+@@ -3151,8 +3151,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
+@@ -1907,7 +1907,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;
+ }
+@@ -1916,6 +1919,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
+@@ -1438,6 +1438,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 df7b59ba9245c4a3115ebaa905e3e5719a3810da Mon Sep 17 00:00:00 2001
+From: Milan Broz <gmazyland@gmail.com>
+Date: Tue, 23 Feb 2021 21:21:21 +0100
+Subject: dm verity: fix FEC for RS roots unaligned to block size
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Milan Broz <gmazyland@gmail.com>
+
+commit df7b59ba9245c4a3115ebaa905e3e5719a3810da upstream.
+
+Optional Forward Error Correction (FEC) code in dm-verity uses
+Reed-Solomon code and should support roots from 2 to 24.
+
+The error correction parity bytes (of roots lengths per RS block) are
+stored on a separate device in sequence without any padding.
+
+Currently, to access FEC device, the dm-verity-fec code uses dm-bufio
+client with block size set to verity data block (usually 4096 or 512
+bytes).
+
+Because this block size is not divisible by some (most!) of the roots
+supported lengths, data repair cannot work for partially stored parity
+bytes.
+
+This fix changes FEC device dm-bufio block size to "roots << SECTOR_SHIFT"
+where we can be sure that the full parity data is always available.
+(There cannot be partial FEC blocks because parity must cover whole
+sectors.)
+
+Because the optional FEC starting offset could be unaligned to this
+new block size, we have to use dm_bufio_set_sector_offset() to
+configure it.
+
+The problem is easily reproduced using veritysetup, e.g. for roots=13:
+
+ # create verity device with RS FEC
+ dd if=/dev/urandom of=data.img bs=4096 count=8 status=none
+ veritysetup format data.img hash.img --fec-device=fec.img --fec-roots=13 | awk '/^Root hash/{ print $3 }' >roothash
+
+ # create an erasure that should be always repairable with this roots setting
+ dd if=/dev/zero of=data.img conv=notrunc bs=1 count=8 seek=4088 status=none
+
+ # try to read it through dm-verity
+ veritysetup open data.img test hash.img --fec-device=fec.img --fec-roots=13 $(cat roothash)
+ dd if=/dev/mapper/test of=/dev/null bs=4096 status=noxfer
+ # wait for possible recursive recovery in kernel
+ udevadm settle
+ veritysetup close test
+
+With this fix, errors are properly repaired.
+ device-mapper: verity-fec: 7:1: FEC 0: corrected 8 errors
+ ...
+
+Without it, FEC code usually ends on unrecoverable failure in RS decoder:
+ device-mapper: verity-fec: 7:1: FEC 0: failed to correct: -74
+ ...
+
+This problem is present in all kernels since the FEC code's
+introduction (kernel 4.5).
+
+It is thought that this problem is not visible in Android ecosystem
+because it always uses a default RS roots=2.
+
+Depends-on: a14e5ec66a7a ("dm bufio: subtract the number of initial sectors in dm_bufio_get_device_size")
+Signed-off-by: Milan Broz <gmazyland@gmail.com>
+Tested-by: Jérôme Carretero <cJ-ko@zougloub.eu>
+Reviewed-by: Sami Tolvanen <samitolvanen@google.com>
+Cc: stable@vger.kernel.org # 4.5+
+Signed-off-by: Mike Snitzer <snitzer@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/md/dm-verity-fec.c | 23 ++++++++++++-----------
+ 1 file changed, 12 insertions(+), 11 deletions(-)
+
+--- a/drivers/md/dm-verity-fec.c
++++ b/drivers/md/dm-verity-fec.c
+@@ -61,19 +61,18 @@ static int fec_decode_rs8(struct dm_veri
+ static u8 *fec_read_parity(struct dm_verity *v, u64 rsb, int index,
+ unsigned *offset, struct dm_buffer **buf)
+ {
+- u64 position, block;
++ u64 position, block, rem;
+ u8 *res;
+
+ position = (index + rsb) * v->fec->roots;
+- block = position >> v->data_dev_block_bits;
+- *offset = (unsigned)(position - (block << v->data_dev_block_bits));
++ block = div64_u64_rem(position, v->fec->roots << SECTOR_SHIFT, &rem);
++ *offset = (unsigned)rem;
+
+- res = dm_bufio_read(v->fec->bufio, v->fec->start + block, buf);
++ res = dm_bufio_read(v->fec->bufio, block, buf);
+ if (IS_ERR(res)) {
+ DMERR("%s: FEC %llu: parity read failed (block %llu): %ld",
+ v->data_dev->name, (unsigned long long)rsb,
+- (unsigned long long)(v->fec->start + block),
+- PTR_ERR(res));
++ (unsigned long long)block, PTR_ERR(res));
+ *buf = NULL;
+ }
+
+@@ -155,7 +154,7 @@ static int fec_decode_bufs(struct dm_ver
+
+ /* read the next block when we run out of parity bytes */
+ offset += v->fec->roots;
+- if (offset >= 1 << v->data_dev_block_bits) {
++ if (offset >= v->fec->roots << SECTOR_SHIFT) {
+ dm_bufio_release(buf);
+
+ par = fec_read_parity(v, rsb, block_offset, &offset, &buf);
+@@ -674,7 +673,7 @@ int verity_fec_ctr(struct dm_verity *v)
+ {
+ struct dm_verity_fec *f = v->fec;
+ struct dm_target *ti = v->ti;
+- u64 hash_blocks;
++ u64 hash_blocks, fec_blocks;
+ int ret;
+
+ if (!verity_fec_is_enabled(v)) {
+@@ -744,15 +743,17 @@ int verity_fec_ctr(struct dm_verity *v)
+ }
+
+ f->bufio = dm_bufio_client_create(f->dev->bdev,
+- 1 << v->data_dev_block_bits,
++ f->roots << SECTOR_SHIFT,
+ 1, 0, NULL, NULL);
+ if (IS_ERR(f->bufio)) {
+ ti->error = "Cannot initialize FEC bufio client";
+ return PTR_ERR(f->bufio);
+ }
+
+- if (dm_bufio_get_device_size(f->bufio) <
+- ((f->start + f->rounds * f->roots) >> v->data_dev_block_bits)) {
++ dm_bufio_set_sector_offset(f->bufio, f->start << (v->data_dev_block_bits - SECTOR_SHIFT));
++
++ fec_blocks = div64_u64(f->rounds * f->roots, v->fec->roots << SECTOR_SHIFT);
++ if (dm_bufio_get_device_size(f->bufio) < fec_blocks) {
+ ti->error = "FEC device is too small";
+ return -E2BIG;
+ }
--- /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
+@@ -240,7 +240,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;
+@@ -283,7 +283,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
+@@ -325,22 +325,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);
+@@ -355,24 +355,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);
+ }
--- /dev/null
+From a5665ec2affdba21bff3b0d4d3aed83b3951e8ff Mon Sep 17 00:00:00 2001
+From: Jarkko Sakkinen <jarkko@kernel.org>
+Date: Sat, 20 Feb 2021 00:55:59 +0200
+Subject: tpm, tpm_tis: Decorate tpm_get_timeouts() with request_locality()
+
+From: Jarkko Sakkinen <jarkko@kernel.org>
+
+commit a5665ec2affdba21bff3b0d4d3aed83b3951e8ff upstream.
+
+This is shown with Samsung Chromebook Pro (Caroline) with TPM 1.2
+(SLB 9670):
+
+[ 4.324298] TPM returned invalid status
+[ 4.324806] WARNING: CPU: 2 PID: 1 at drivers/char/tpm/tpm_tis_core.c:275 tpm_tis_status+0x86/0x8f
+
+Background
+==========
+
+TCG PC Client Platform TPM Profile (PTP) Specification, paragraph 6.1 FIFO
+Interface Locality Usage per Register, Table 39 Register Behavior Based on
+Locality Setting for FIFO - a read attempt to TPM_STS_x Registers returns
+0xFF in case of lack of locality.
+
+The fix
+=======
+
+Decorate tpm_get_timeouts() with request_locality() and release_locality().
+
+Fixes: a3fbfae82b4c ("tpm: take TPM chip power gating out of tpm_transmit()")
+Cc: James Bottomley <James.Bottomley@HansenPartnership.com>
+Cc: Guenter Roeck <linux@roeck-us.net>
+Cc: Laurent Bigonville <bigon@debian.org>
+Cc: stable@vger.kernel.org
+Reported-by: Lukasz Majczak <lma@semihalf.com>
+Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/char/tpm/tpm_tis_core.c | 14 ++++++++++++--
+ 1 file changed, 12 insertions(+), 2 deletions(-)
+
+--- a/drivers/char/tpm/tpm_tis_core.c
++++ b/drivers/char/tpm/tpm_tis_core.c
+@@ -939,11 +939,21 @@ int tpm_tis_core_init(struct device *dev
+ init_waitqueue_head(&priv->read_queue);
+ init_waitqueue_head(&priv->int_queue);
+ if (irq != -1) {
+- /* Before doing irq testing issue a command to the TPM in polling mode
++ /*
++ * Before doing irq testing issue a command to the TPM in polling mode
+ * to make sure it works. May as well use that command to set the
+ * proper timeouts for the driver.
+ */
+- if (tpm_get_timeouts(chip)) {
++
++ rc = request_locality(chip, 0);
++ if (rc < 0)
++ goto out_err;
++
++ rc = tpm_get_timeouts(chip);
++
++ release_locality(chip, 0);
++
++ if (rc) {
+ dev_err(dev, "Could not get TPM timeouts and durations\n");
+ rc = -ENODEV;
+ goto out_err;
--- /dev/null
+From d53a6adfb553969809eb2b736a976ebb5146cd95 Mon Sep 17 00:00:00 2001
+From: Lukasz Majczak <lma@semihalf.com>
+Date: Tue, 16 Feb 2021 10:17:49 +0200
+Subject: tpm, tpm_tis: Decorate tpm_tis_gen_interrupt() with request_locality()
+
+From: Lukasz Majczak <lma@semihalf.com>
+
+commit d53a6adfb553969809eb2b736a976ebb5146cd95 upstream.
+
+This is shown with Samsung Chromebook Pro (Caroline) with TPM 1.2
+(SLB 9670):
+
+[ 4.324298] TPM returned invalid status
+[ 4.324806] WARNING: CPU: 2 PID: 1 at drivers/char/tpm/tpm_tis_core.c:275 tpm_tis_status+0x86/0x8f
+
+Background
+==========
+
+TCG PC Client Platform TPM Profile (PTP) Specification, paragraph 6.1 FIFO
+Interface Locality Usage per Register, Table 39 Register Behavior Based on
+Locality Setting for FIFO - a read attempt to TPM_STS_x Registers returns
+0xFF in case of lack of locality.
+
+The fix
+=======
+
+Decorate tpm_tis_gen_interrupt() with request_locality() and
+release_locality().
+
+Cc: Laurent Bigonville <bigon@debian.org>
+Cc: James Bottomley <James.Bottomley@HansenPartnership.com>
+Cc: Guenter Roeck <linux@roeck-us.net>
+Cc: stable@vger.kernel.org
+Fixes: a3fbfae82b4c ("tpm: take TPM chip power gating out of tpm_transmit()")
+Signed-off-by: Lukasz Majczak <lma@semihalf.com>
+Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/char/tpm/tpm_tis_core.c | 16 +++++++++++++---
+ 1 file changed, 13 insertions(+), 3 deletions(-)
+
+--- a/drivers/char/tpm/tpm_tis_core.c
++++ b/drivers/char/tpm/tpm_tis_core.c
+@@ -618,12 +618,22 @@ static int tpm_tis_gen_interrupt(struct
+ const char *desc = "attempting to generate an interrupt";
+ u32 cap2;
+ cap_t cap;
++ int ret;
+
++ /* TPM 2.0 */
+ if (chip->flags & TPM_CHIP_FLAG_TPM2)
+ return tpm2_get_tpm_pt(chip, 0x100, &cap2, desc);
+- else
+- return tpm1_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, &cap, desc,
+- 0);
++
++ /* TPM 1.2 */
++ ret = request_locality(chip, 0);
++ if (ret < 0)
++ return ret;
++
++ ret = tpm1_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, &cap, desc, 0);
++
++ release_locality(chip, 0);
++
++ return ret;
+ }
+
+ /* Register the IRQ and issue a command that will cause an interrupt. If an