Skip to content

Commit 03f018b

Browse files
Li kunyukernel-patches-daemon
authored andcommitted
block/blk-iolatency: Add the processing flow of the chained bio in the QoS and define the related types to solve the problem of incorrect inflight processing in the QoS. The usage of the done_split_bio abstract function in the blk-iolatency project.
Signed-off-by: Li kunyu <[email protected]>
1 parent 25a041f commit 03f018b

5 files changed

Lines changed: 55 additions & 1 deletion

File tree

block/bio.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1733,6 +1733,8 @@ static inline bool bio_remaining_done(struct bio *bio)
17331733
return true;
17341734
}
17351735

1736+
rq_qos_done_split_bio(bio);
1737+
17361738
return false;
17371739
}
17381740

block/blk-iolatency.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -632,6 +632,39 @@ static void blkcg_iolatency_done_bio(struct rq_qos *rqos, struct bio *bio)
632632
}
633633
}
634634

635+
static void blkcg_iolatency_done_split_bio(struct rq_qos *rqos, struct bio *bio)
636+
{
637+
struct blkcg_gq *blkg;
638+
struct rq_wait *rqw;
639+
struct iolatency_grp *iolat;
640+
int inflight = 0;
641+
642+
blkg = bio->bi_blkg;
643+
if (!blkg || !bio_flagged(bio, BIO_QOS_CHAIN_CHILD))
644+
return;
645+
646+
iolat = blkg_to_lat(bio->bi_blkg);
647+
if (!iolat)
648+
return;
649+
650+
if (!iolat->blkiolat->enabled)
651+
return;
652+
653+
while (blkg && blkg->parent) {
654+
iolat = blkg_to_lat(blkg);
655+
if (!iolat) {
656+
blkg = blkg->parent;
657+
continue;
658+
}
659+
rqw = &iolat->rq_wait;
660+
661+
inflight = atomic_dec_return(&rqw->inflight);
662+
WARN_ON_ONCE(inflight < 0);
663+
664+
blkg = blkg->parent;
665+
}
666+
}
667+
635668
static void blkcg_iolatency_exit(struct rq_qos *rqos)
636669
{
637670
struct blk_iolatency *blkiolat = BLKIOLATENCY(rqos);
@@ -645,6 +678,7 @@ static void blkcg_iolatency_exit(struct rq_qos *rqos)
645678
static const struct rq_qos_ops blkcg_iolatency_ops = {
646679
.throttle = blkcg_iolatency_throttle,
647680
.done_bio = blkcg_iolatency_done_bio,
681+
.done_split_bio = blkcg_iolatency_done_split_bio,
648682
.exit = blkcg_iolatency_exit,
649683
};
650684

block/blk-merge.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,8 +151,13 @@ static struct bio *bio_submit_split(struct bio *bio, int split_sectors)
151151
if (split_sectors) {
152152
bio = bio_submit_split_bioset(bio, split_sectors,
153153
&bio->bi_bdev->bd_disk->bio_split);
154-
if (bio)
154+
if (bio) {
155155
bio->bi_opf |= REQ_NOMERGE;
156+
/* Fix the issue where the inflight statistics
157+
* of the chained bio in the QoS are incorrect.
158+
*/
159+
bio_set_flag(split, BIO_QOS_CHAIN_CHILD);
160+
}
156161
}
157162

158163
return bio;

block/blk-rq-qos.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ struct rq_qos_ops {
4545
void (*cleanup)(struct rq_qos *, struct bio *);
4646
void (*queue_depth_changed)(struct rq_qos *);
4747
void (*exit)(struct rq_qos *);
48+
void (*done_split_bio)(struct rq_qos *, struct bio *);
4849
const struct blk_mq_debugfs_attr *debugfs_attrs;
4950
};
5051

@@ -108,6 +109,7 @@ void __rq_qos_throttle(struct rq_qos *rqos, struct bio *bio);
108109
void __rq_qos_track(struct rq_qos *rqos, struct request *rq, struct bio *bio);
109110
void __rq_qos_merge(struct rq_qos *rqos, struct request *rq, struct bio *bio);
110111
void __rq_qos_done_bio(struct rq_qos *rqos, struct bio *bio);
112+
void __rq_qos_done_split_bio(struct rq_qos *rqos, struct bio *bio);
111113
void __rq_qos_queue_depth_changed(struct rq_qos *rqos);
112114

113115
static inline void rq_qos_cleanup(struct request_queue *q, struct bio *bio)
@@ -157,6 +159,15 @@ static inline void rq_qos_done_bio(struct bio *bio)
157159
__rq_qos_done_bio(q->rq_qos, bio);
158160
}
159161

162+
static inline void rq_qos_done_split_bio(struct bio *bio)
163+
{
164+
if (bio->bi_bdev && bio_flagged(bio, BIO_QOS_CHAIN_CHILD)) {
165+
struct request_queue *q = bdev_get_queue(bio->bi_bdev);
166+
if (q->rq_qos)
167+
__rq_qos_done_split_bio(q->rq_qos, bio);
168+
}
169+
}
170+
160171
static inline void rq_qos_throttle(struct request_queue *q, struct bio *bio)
161172
{
162173
if (test_bit(QUEUE_FLAG_QOS_ENABLED, &q->queue_flags) && q->rq_qos) {

include/linux/blk_types.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,8 @@ enum {
322322
BIO_REMAPPED,
323323
BIO_ZONE_WRITE_PLUGGING, /* bio handled through zone write plugging */
324324
BIO_EMULATES_ZONE_APPEND, /* bio emulates a zone append operation */
325+
BIO_QOS_CHAIN_CHILD, /* chained bio child, used for segmenting out
326+
* the bio */
325327
BIO_FLAG_LAST
326328
};
327329

0 commit comments

Comments
 (0)