--- /dev/null
+From 32025413729969c7ce159fa58ee590f6cd0c2657 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 18 Jun 2020 19:30:22 +0100
+Subject: blk-mq: move blk_mq_update_nr_hw_queues synchronize_rcu call
+
+From: Giuliano Procida <gprocida@google.com>
+
+This fixes the
+4.9 backport commit f530afb974c2e82047bd6220303a2dbe30eff304
+which was
+upstream commit f5bbbbe4d63577026f908a809f22f5fd5a90ea1f.
+
+The upstream commit added a call to synchronize_rcu to
+_blk_mq_update_nr_hw_queues, just after freezing queues.
+
+In the backport this landed (in blk_mq_update_nr_hw_queues instead),
+just after unfreezeing queues.
+
+This commit moves the call to its intended place.
+
+Fixes: f530afb974c2 ("blk-mq: sync the update nr_hw_queues with blk_mq_queue_tag_busy_iter")
+Signed-off-by: Giuliano Procida <gprocida@google.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ block/blk-mq.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/block/blk-mq.c b/block/blk-mq.c
+index 58be2eaa5aaa..e0ed7317e98c 100644
+--- a/block/blk-mq.c
++++ b/block/blk-mq.c
+@@ -2331,6 +2331,10 @@ void blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set, int nr_hw_queues)
+
+ list_for_each_entry(q, &set->tag_list, tag_set_list)
+ blk_mq_freeze_queue(q);
++ /*
++ * Sync with blk_mq_queue_tag_busy_iter.
++ */
++ synchronize_rcu();
+
+ set->nr_hw_queues = nr_hw_queues;
+ list_for_each_entry(q, &set->tag_list, tag_set_list) {
+@@ -2346,10 +2350,6 @@ void blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set, int nr_hw_queues)
+
+ list_for_each_entry(q, &set->tag_list, tag_set_list)
+ blk_mq_unfreeze_queue(q);
+- /*
+- * Sync with blk_mq_queue_tag_busy_iter.
+- */
+- synchronize_rcu();
+ }
+ EXPORT_SYMBOL_GPL(blk_mq_update_nr_hw_queues);
+
+--
+2.25.1
+
--- /dev/null
+From b9d08cbe6afab162671d7dc39d0fe7d0ec22b39d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 16 Apr 2020 14:46:12 -0700
+Subject: btrfs: fix error handling when submitting direct I/O bio
+
+From: Omar Sandoval <osandov@fb.com>
+
+[ Upstream commit 6d3113a193e3385c72240096fe397618ecab6e43 ]
+
+In btrfs_submit_direct_hook(), if a direct I/O write doesn't span a RAID
+stripe or chunk, we submit orig_bio without cloning it. In this case, we
+don't increment pending_bios. Then, if btrfs_submit_dio_bio() fails, we
+decrement pending_bios to -1, and we never complete orig_bio. Fix it by
+initializing pending_bios to 1 instead of incrementing later.
+
+Fixing this exposes another bug: we put orig_bio prematurely and then
+put it again from end_io. Fix it by not putting orig_bio.
+
+After this change, pending_bios is really more of a reference count, but
+I'll leave that cleanup separate to keep the fix small.
+
+Fixes: e65e15355429 ("btrfs: fix panic caused by direct IO")
+CC: stable@vger.kernel.org # 4.4+
+Reviewed-by: Nikolay Borisov <nborisov@suse.com>
+Reviewed-by: Josef Bacik <josef@toxicpanda.com>
+Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
+Signed-off-by: Omar Sandoval <osandov@fb.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/inode.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
+index 250c8403ec67..c425443c31fe 100644
+--- a/fs/btrfs/inode.c
++++ b/fs/btrfs/inode.c
+@@ -8494,7 +8494,6 @@ static int btrfs_submit_direct_hook(struct btrfs_dio_private *dip,
+ bio->bi_private = dip;
+ bio->bi_end_io = btrfs_end_dio_bio;
+ btrfs_io_bio(bio)->logical = file_offset;
+- atomic_inc(&dip->pending_bios);
+
+ while (bvec <= (orig_bio->bi_io_vec + orig_bio->bi_vcnt - 1)) {
+ nr_sectors = BTRFS_BYTES_TO_BLKS(root->fs_info, bvec->bv_len);
+@@ -8560,7 +8559,8 @@ static int btrfs_submit_direct_hook(struct btrfs_dio_private *dip,
+ if (!ret)
+ return 0;
+
+- bio_put(bio);
++ if (bio != orig_bio)
++ bio_put(bio);
+ out_err:
+ dip->errors = 1;
+ /*
+@@ -8607,7 +8607,7 @@ static void btrfs_submit_direct(struct bio *dio_bio, struct inode *inode,
+ io_bio->bi_private = dip;
+ dip->orig_bio = io_bio;
+ dip->dio_bio = dio_bio;
+- atomic_set(&dip->pending_bios, 0);
++ atomic_set(&dip->pending_bios, 1);
+ btrfs_bio = btrfs_io_bio(io_bio);
+ btrfs_bio->logical = file_offset;
+
+--
+2.25.1
+