summaryrefslogtreecommitdiff
path: root/block
diff options
context:
space:
mode:
Diffstat (limited to 'block')
-rw-r--r--block/blk-merge.c26
-rw-r--r--block/blk-zoned.c8
-rw-r--r--block/genhd.c26
3 files changed, 34 insertions, 26 deletions
diff --git a/block/blk-merge.c b/block/blk-merge.c
index 3af1d284add5..70d704615be5 100644
--- a/block/blk-merge.c
+++ b/block/blk-merge.c
@@ -998,20 +998,20 @@ bool blk_attempt_plug_merge(struct request_queue *q, struct bio *bio,
if (!plug || rq_list_empty(&plug->mq_list))
return false;
- rq_list_for_each(&plug->mq_list, rq) {
- if (rq->q == q) {
- if (blk_attempt_bio_merge(q, rq, bio, nr_segs, false) ==
- BIO_MERGE_OK)
- return true;
- break;
- }
+ rq = plug->mq_list.tail;
+ if (rq->q == q)
+ return blk_attempt_bio_merge(q, rq, bio, nr_segs, false) ==
+ BIO_MERGE_OK;
+ else if (!plug->multiple_queues)
+ return false;
- /*
- * Only keep iterating plug list for merges if we have multiple
- * queues
- */
- if (!plug->multiple_queues)
- break;
+ rq_list_for_each(&plug->mq_list, rq) {
+ if (rq->q != q)
+ continue;
+ if (blk_attempt_bio_merge(q, rq, bio, nr_segs, false) ==
+ BIO_MERGE_OK)
+ return true;
+ break;
}
return false;
}
diff --git a/block/blk-zoned.c b/block/blk-zoned.c
index 8f15d1aa6eb8..351d659280e1 100644
--- a/block/blk-zoned.c
+++ b/block/blk-zoned.c
@@ -1225,6 +1225,7 @@ void blk_zone_write_plug_bio_endio(struct bio *bio)
if (bio_flagged(bio, BIO_EMULATES_ZONE_APPEND)) {
bio->bi_opf &= ~REQ_OP_MASK;
bio->bi_opf |= REQ_OP_ZONE_APPEND;
+ bio_clear_flag(bio, BIO_EMULATES_ZONE_APPEND);
}
/*
@@ -1306,7 +1307,6 @@ again:
spin_unlock_irqrestore(&zwplug->lock, flags);
bdev = bio->bi_bdev;
- submit_bio_noacct_nocheck(bio);
/*
* blk-mq devices will reuse the extra reference on the request queue
@@ -1314,8 +1314,12 @@ again:
* path for BIO-based devices will not do that. So drop this extra
* reference here.
*/
- if (bdev_test_flag(bdev, BD_HAS_SUBMIT_BIO))
+ if (bdev_test_flag(bdev, BD_HAS_SUBMIT_BIO)) {
+ bdev->bd_disk->fops->submit_bio(bio);
blk_queue_exit(bdev->bd_disk->queue);
+ } else {
+ blk_mq_submit_bio(bio);
+ }
put_zwplug:
/* Drop the reference we took in disk_zone_wplug_schedule_bio_work(). */
diff --git a/block/genhd.c b/block/genhd.c
index 8171a6bc3210..c26733f6324b 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -128,23 +128,27 @@ static void part_stat_read_all(struct block_device *part,
static void bdev_count_inflight_rw(struct block_device *part,
unsigned int inflight[2], bool mq_driver)
{
+ int write = 0;
+ int read = 0;
int cpu;
if (mq_driver) {
blk_mq_in_driver_rw(part, inflight);
- } else {
- for_each_possible_cpu(cpu) {
- inflight[READ] += part_stat_local_read_cpu(
- part, in_flight[READ], cpu);
- inflight[WRITE] += part_stat_local_read_cpu(
- part, in_flight[WRITE], cpu);
- }
+ return;
+ }
+
+ for_each_possible_cpu(cpu) {
+ read += part_stat_local_read_cpu(part, in_flight[READ], cpu);
+ write += part_stat_local_read_cpu(part, in_flight[WRITE], cpu);
}
- if (WARN_ON_ONCE((int)inflight[READ] < 0))
- inflight[READ] = 0;
- if (WARN_ON_ONCE((int)inflight[WRITE] < 0))
- inflight[WRITE] = 0;
+ /*
+ * While iterating all CPUs, some IOs may be issued from a CPU already
+ * traversed and complete on a CPU that has not yet been traversed,
+ * causing the inflight number to be negative.
+ */
+ inflight[READ] = read > 0 ? read : 0;
+ inflight[WRITE] = write > 0 ? write : 0;
}
/**